Skip to content

Instantly share code, notes, and snippets.

@sunmeat
Created June 3, 2025 06:15
Show Gist options
  • Save sunmeat/34cf8d9f1260155e70c98e79d8e50577 to your computer and use it in GitHub Desktop.
Save sunmeat/34cf8d9f1260155e70c98e79d8e50577 to your computer and use it in GitHub Desktop.
tanstack query example react + localStorage
import {useState, useEffect} from 'react';
import {QueryClient, QueryClientProvider, useQuery} from '@tanstack/react-query';
import './App.css';
const truncateText = (text, maxLength) => {
if (text.length > maxLength) {
return text.slice(0, maxLength) + '...';
}
return text;
};
// экземпляр QueryClient
const queryClient = new QueryClient();
// компонента для получения и отображения продуктов
function ProductList({addToCart}) {
// API для получения продуктов
const fetchProducts = async () => {
const response = await fetch('https://fakestoreapi.com/products?limit=12');
if (!response.ok) throw new Error('Ошибка загрузки продуктов');
return response.json();
};
// useQuery для управления данными
const {data, error, isLoading} = useQuery({
queryKey: ['products'],
queryFn: fetchProducts,
staleTime: 5 * 60 * 1000, // кэширование на 5 минут
});
if (isLoading) return <div className="loading">Загрузка...</div>;
if (error) return <div className="error">Ошибка: {error.message}</div>;
return (
<div className="product-list">
<h2>Наши товары:</h2>
<div className="products">
{data.map((product) => (
<div key={product.id} className="product-card">
<img src={product.image} alt={product.title} className="product-image"/>
<h3>{truncateText(product.title, 30)}</h3>
<p className="price">${product.price}</p>
<button onClick={() => addToCart(product)} className="add-to-cart">
Добавить в корзину
</button>
</div>
))}
</div>
</div>
);
}
// компонента корзины
function Cart({cart, removeFromCart}) {
const total = cart.reduce((sum, item) => sum + item.price, 0).toFixed(2);
return (
<div className="cart">
<h2>Корзина</h2>
{cart.length === 0 ? (
<p>Корзина пуста</p>
) : (
<div>
{cart.map((item) => (
<div key={item.id} className="cart-item">
<span>{truncateText(item.title, 30)}</span>
<span>${item.price}</span>
<button onClick={() => removeFromCart(item.id)} className="remove-from-cart">
Удалить
</button>
</div>
))}
<p className="total">Итого: ${total}</p>
</div>
)}
</div>
);
}
function App() {
// инициализация состояния корзины из localStorage
const [cart, setCart] = useState(() => {
const savedCart = localStorage.getItem('cart');
return savedCart ? JSON.parse(savedCart) : [];
});
// синхронизация корзины с localStorage при каждом изменении
useEffect(() => {
localStorage.setItem('cart', JSON.stringify(cart));
}, [cart]);
const addToCart = (product) => {
setCart((prevCart) => [...prevCart, product]);
};
const removeFromCart = (productId) => {
setCart((prevCart) => prevCart.filter((item) => item.id !== productId));
};
return (
<QueryClientProvider client={queryClient}>
<div className="app">
<h1>Интернет-магазин ReactExpress</h1>
<ProductList addToCart={addToCart}/>
<Cart cart={cart} removeFromCart={removeFromCart}/>
</div>
</QueryClientProvider>
);
}
export default App;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment