React Query ilə Server State: Artıq useEffect Yazma, Qardaş
Hələ də useEffect + useState ilə API çağırırsan? React Query ilə server state idarəetməsini öyrən, kodu 60% azalt, UX-i 10x yaxşılaş.
React Query ilə Server State İdarəetməsi: Tam Praktiki Bələdçi
Salam, developer dostum. Əgər bu gün Bakıda hər hansı bir startupda və ya outsource şirkətdə React layihəsində işləyirsənsə, 90% ehtimal var ki, bu pattern-i görmüsən:
javascriptconst [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { fetch('/api/products') .then(res => res.json()) .then(data => setData(data)) .catch(err => setError(err)) .finally(() => setLoading(false)); }, []);
Tanış gəldi, elə deyil? Hər komponentdə eyni 12-15 sətir boilerplate. Race condition-lar, stale data, cache problemi... Bütün bunları əl ilə həll etməyə çalışırsan. Artıq buna ehtiyac yoxdur.
React Query (TanStack Query) tam olaraq bu problemi həll edir — və bu gün sənə real layihə nümunəsi ilə göstərəcəm.
Server State nədir və niyə fərqlidir?
Əvvəlcə vacib bir ayrım edək:
- Client State: Modal açıqdır/bağlıdır, seçilmiş tab, form input-ları — bunlar istifadəçinin brauzerində yaranır.
- Server State: İstifadəçi siyahısı, məhsul kataloqu, sifariş tarixi — bunlar serverdə yaşayır, sən yalnız kopyasını göstərirsən.
Problem ondadır ki, çoxumuz Redux və ya Zustand kimi client state alətləri ilə server state-i idarə etməyə çalışırıq. Bu, mismar çalmaq üçün mikroskop istifadə etmək kimidir.
Server state-in unikal xüsusiyyətləri var:
- Sənin nəzarətindən kənardadır
- Köhnələ bilər (stale olur)
- Asinxrondur
- Başqa istifadəçilər tərəfindən dəyişdirilə bilər
React Query Quraşdırma
Başlayaq. Layihənə əlavə et:
bashnpm install @tanstack/react-query @tanstack/react-query-devtools
Əvvəlcə QueryClientProvider ilə app-i sarımaq lazımdır:
javascript// main.jsx import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; const queryClient = new QueryClient({ defaultOptions: { queries: { staleTime: 5 * 60 * 1000, // 5 dəqiqə retry: 2, }, }, }); function App() { return ( <QueryClientProvider client={queryClient}> <Router /> <ReactQueryDevtools initialIsOpen={false} /> </QueryClientProvider> ); }
Real Layihə Nümunəsi: Məhsul Kataloqu
Təsəvvür et ki, Bakıdakı bir e-commerce startupda işləyirsən. Məhsul siyahısı, filtrasiya və ayrı-ayrı məhsul səhifələri lazımdır. React Query ilə bunu necə qururuq:
1. API Layer
javascript// api/products.js const BASE_URL = 'https://api.example.az/v1'; export const fetchProducts = async ({ page = 1, category }) => { const params = new URLSearchParams({ page, ...(category && { category }) }); const res = await fetch(`${BASE_URL}/products?${params}`); if (!res.ok) throw new Error('Məhsullar yüklənmədi'); return res.json(); }; export const fetchProductById = async (id) => { const res = await fetch(`${BASE_URL}/products/${id}`); if (!res.ok) throw new Error('Məhsul tapılmadı'); return res.json(); }; export const createProduct = async (newProduct) => { const res = await fetch(`${BASE_URL}/products`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(newProduct), }); if (!res.ok) throw new Error('Məhsul yaradılmadı'); return res.json(); };
2. Custom Hooks (ən vacib hissə)
javascript// hooks/useProducts.js import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { fetchProducts, fetchProductById, createProduct } from '../api/products'; // Məhsul siyahısı export const useProducts = (page, category) => { return useQuery({ queryKey: ['products', { page, category }], queryFn: () => fetchProducts({ page, category }), placeholderData: (previousData) => previousData, }); }; // Tək məhsul export const useProduct = (id) => { return useQuery({ queryKey: ['products', id], queryFn: () => fetchProductById(id), enabled: !!id, // id olmasa, sorğu getməsin }); }; // Yeni məhsul yarat export const useCreateProduct = () => { const queryClient = useQueryClient(); return useMutation({ mutationFn: createProduct, onSuccess: () => { // Məhsul siyahısını yenilə queryClient.invalidateQueries({ queryKey: ['products'] }); }, }); };
3. Komponentdə İstifadə
Bax, indi gör kod nə qədər təmiz olur:
javascript// components/ProductList.jsx import { useProducts } from '../hooks/useProducts'; export default function ProductList() { const [page, setPage] = useState(1); const [category, setCategory] = useState(null); const { data, isLoading, isError, error, isPlaceholderData } = useProducts(page, category); if (isLoading) return <Skeleton count={6} />; if (isError) return <ErrorMessage message={error.message} />; return ( <div> <CategoryFilter value={category} onChange={setCategory} /> <div className="grid grid-cols-3 gap-4"> {data.products.map(product => ( <ProductCard key={product.id} product={product} /> ))} </div> <Pagination page={page} totalPages={data.totalPages} onPageChange={setPage} disabled={isPlaceholderData} /> </div> ); }
Əvvəlki 30-40 sətir kod indi 20 sətirə düşdü. Loading, error, caching — hamısı avtomatik.
React Query-nin Sənə Verdiyi Supergüclər
- Avtomatik caching: Eyni sorğu təkrar getmir, cache-dən oxuyur
- Background refetch: İstifadəçi tab-a qayıdanda data avtomatik yenilənir
- Stale-while-revalidate: Köhnə datanı göstər, arxa planda yenisini gətir
- Retry: Sorğu uğursuz olsa, avtomatik təkrar cəhd
- Pagination & Infinite Scroll: Daxili dəstək
- Optimistic Updates: UI-ı server cavabından əvvəl yenilə
- DevTools: Cache-in içini real-time gör
Rəqəmlərlə Fərq
Şirkətimizdə (300+ komponentli React layihə) React Query-yə keçiddən sonra gördüyümüz nəticələr:
| Metrika | Əvvəl | Sonra |
|---|---|---|
| API-related boilerplate sətir | ~4200 | ~1600 |
| Gereksiz network request | ~120/dəq | ~35/dəq |
| Ortalama loading vaxtı (perceived) | 1.8s | 0.4s |
| Data-related bug-lar (aylıq) | 15-20 | 2-3 |
Bu rəqəmlər təxminidir, amma trend hər layihədə eynidir.
Bakı Developer Bazarı üçün Niyə Vacibdir?
Bu gün Bakıda Junior React Developer maaşı 800-1200 AZN, Middle 1500-2500 AZN, Senior isə 3000-5000 AZN aralığındadır. Sənin Middle-dan Senior-a keçid etmək üçün fərqləndirici biliklərə ehtiyacın var.
React Query (TanStack Query) artıq standartdır. ABB, Kapital Bank kimi böyük şirkətlərin digital komandaları, Azərbaycan startupları — hamı bu yanaşmaya keçir. İş müsahibələrində "server state management" sualı artıq klassik sualdır.
Qızıl Qaydalar
- queryKey-i düzgün strukturlaşdır —
['products', { page, category }]formatı filtrasiyada cache-i avtomatik ayırır - staleTime-ı biznes məntiqinə görə seç — tez dəyişən data üçün 30 saniyə, statik data üçün 30 dəqiqə
- enabled parametrini unutma — dependent query-lər üçün mütləqdir
- Error boundary ilə birlikdə istifadə et —
throwOnError: trueilə React Error Boundary-yə yönləndir - DevTools-u həmişə aktiv saxla — development-də cache-in nə vəziyyətdə olduğunu görmək qızıl dəyərindədir
Nəticə
useEffect + useState ilə API çağırmaq 2023-də bitdi. 2026-da React layihəsində server state üçün React Query istifadə etməmək, texniki borcun əsas mənbəyidir.
Bu gün bir komponentini refactor et. Fərqi öz gözünlə gör. Sonra geri dönüş yoxdur.
Sualın varsa, kommentdə yaz. Bakı dev community olaraq bir-birimizə kömək edək. 🚀
Növbəti məqalə: "React Query + Zustand: Server və Client State-in mükəmməl harmoniyası"
Oxşar məqalələr
React-da Performans: useMemo və useCallback — Nə Vaxt Lazımdır?
useMemo və useCallback hər yerə yazmaq reflex olub? Gəl birlikdə anlayaq: bu hook-lar nə vaxt həqiqətən lazımdır, nə vaxt isə əksinə — zərərdir.
React Query ilə Server State: useState-dən Qurtuluş Yolu
Hələ də API datanı useState + useEffect ilə idarə edirsən? React Query ilə server state-i necə peşəkar səviyyədə idarə etməyi öyrən.
React Server Components — Nə Vaxt İstifadə Etməli, Nə Vaxt Yox?
RSC hər yerə lazım deyil. Bu məqalədə real kod nümunələri ilə Server Components-in nə vaxt performans artırdığını, nə vaxt isə əngəl olduğunu izah edirik.