Blog/react/React Query ilə Server State: Artıq useEffect Cəhənnəmində Yaşama
react

React Query ilə Server State: Artıq useEffect Cəhənnəmində Yaşama

B
Baku Stack AI
·1 mart 2026·5 dəq oxuma·38 baxış
react.ascii
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓ ■ ■ ■ REACT QUERY ▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓ useQuery() ▓
▓ → fresh ▓▓▓▓▓░░░ ▓
▓ → stale ▓▓▓░░░░░ ▓
▓ → fetch ▓▓▓▓▓▓▓░ ▓
▓ ● cache ✓ 5 dəq ▓
▓ ● retry ✓ 3 dəfə ▓
▓ ● dedup ✓ auto ▓
▓──────────────────────▓
▓ useMutation() ▓
▓ POST → invalidate↓ ▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

useEffect + useState ilə API çağırışları yazmaqdan yoruldun? React Query (TanStack Query) ilə server state idarəetməsini kökündən dəyiş.

React Query ilə Server State: Artıq useEffect Cəhənnəmində Yaşama

Bakıda bir frontend müsahibəyə gedirsən. HR sənə "Redux bilirsiniz?" deyir, sən "bəli" deyirsən. Sonra texniki müsahibədə senior developer soruşur: "Server state ilə client state arasındakı fərq nədir və niyə bunları eyni yerdə saxlamaq problemdir?" — və otaqda sükut çökür.

Bu məqalədə həmin suala cavab verəcəyik. Və cavab bir addan ibarətdir: React Query (indi rəsmi adı TanStack Query).


Problem: useEffect Cəhənnəmi

Bunu hamımız yazmışıq:

jsx
const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { let cancelled = false; setLoading(true); fetch('/api/products') .then(res => res.json()) .then(json => { if (!cancelled) { setData(json); setLoading(false); } }) .catch(err => { if (!cancelled) { setError(err); setLoading(false); } }); return () => { cancelled = true; }; }, []);

3 dənə useState, 1 dənə useEffect, race condition üçün cancelled flag, error handling... Və bu bir endpoint üçündür. Layihədə 40 endpoint varsa nə baş verir? Cavab: xaos.

Bu pattern-in əsas problemləri:

  • Caching yoxdur — hər component mount olanda yenidən fetch edir
  • Stale data — istifadəçi tab-a qayıdanda köhnə data görür
  • Deduplication yoxdur — eyni endpoint-ə 5 component eyni anda 5 request göndərir
  • Loading/error state boilerplate — hər səhifədə eyni kodu yazırsan

Həll: React Query

React Query server state üçün xüsusi yaradılmış kitabxanadır. Client state (modal açıq/bağlı, form input-ları) üçün deyil — serverdən gələn data üçündür.

Quraşdırma:

bash
npm install @tanstack/react-query

Əvvəlcə provider qur:

jsx
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; const queryClient = new QueryClient(); function App() { return ( <QueryClientProvider client={queryClient}> <YourApp /> </QueryClientProvider> ); }

İndi yuxarıdakı 15 sətirlik kodu 3 sətirə endirək:

jsx
import { useQuery } from '@tanstack/react-query'; function Products() { const { data, isLoading, error } = useQuery({ queryKey: ['products'], queryFn: () => fetch('/api/products').then(res => res.json()), }); if (isLoading) return <Spinner />; if (error) return <ErrorMessage error={error} />; return ( <ul> {data.map(product => ( <li key={product.id}>{product.name}{product.price} AZN</li> ))} </ul> ); }

Bu 3 sətirlik hook sənə nə verir:

  • Avtomatik caching — eyni queryKey ilə ikinci component mount olsa, cache-dən oxuyur
  • Background refetching — istifadəçi tab-a qayıdanda data sessiz yenilənir
  • Deduplication — eyni anda 5 component eyni key istəsə, 1 request gedir
  • Retry — request uğursuz olsa, avtomatik 3 dəfə təkrar cəhd edir
  • Garbage collection — component unmount olandan 5 dəqiqə sonra cache təmizlənir

Real Ssenari: E-commerce Admin Panel

Tutaq ki, Bakıda bir startapda işləyirsən (məsələn, iş elanları və ya e-ticarət platforması) və admin paneldə sifarişləri idarə etməlisən. Sifariş siyahısını göstərmək, yeni sifariş əlavə etmək lazımdır.

Data çəkmək — useQuery

jsx
function OrderList() { const { data: orders, isLoading } = useQuery({ queryKey: ['orders', { status: 'pending' }], queryFn: () => api.get('/orders?status=pending'), staleTime: 30 * 1000, // 30 saniyə ərzində yenidən fetch etmə refetchOnWindowFocus: true, // tab-a qayıdanda yenilə }); if (isLoading) return <TableSkeleton rows={10} />; return ( <table> <thead> <tr><th>ID</th><th>Müştəri</th><th>Məbləğ</th></tr> </thead> <tbody> {orders.map(order => ( <tr key={order.id}> <td>#{order.id}</td> <td>{order.customerName}</td> <td>{order.total} AZN</td> </tr> ))} </tbody> </table> ); }

Data dəyişmək — useMutation

Mutation — POST, PUT, DELETE əməliyyatları üçündür:

jsx
import { useMutation, useQueryClient } from '@tanstack/react-query'; function CreateOrder() { const queryClient = useQueryClient(); const mutation = useMutation({ mutationFn: (newOrder) => api.post('/orders', newOrder), onSuccess: () => { // Sifariş yaradıldıqdan sonra siyahını yenilə queryClient.invalidateQueries({ queryKey: ['orders'] }); }, }); const handleSubmit = (formData) => { mutation.mutate({ customerName: formData.name, total: formData.amount, }); }; return ( <form onSubmit={handleSubmit}> {/* form fields */} <button disabled={mutation.isPending}> {mutation.isPending ? 'Göndərilir...' : 'Sifariş yarat'} </button> {mutation.isError && <p>Xəta baş verdi, yenidən cəhd et</p>} </form> ); }

invalidateQueries çağırıldıqda React Query avtomatik olaraq ['orders'] key-li bütün query-ləri yenidən fetch edir. Əllə heç nə yazmağa ehtiyac yoxdur.


staleTime vs gcTime (cacheTime)

Bu iki konsepti qarışdıranlar çoxdur:

ParametrDefoltNə edir
staleTime0Data nə qədər "təzə" sayılır. 0 = hər zaman stale
gcTime5 dəqiqəInactive query cache-dən nə zaman silinir

Praktiki məsləhət: API-n çox dəyişmirsə (məsələn, kateqoriya siyahısı), staleTime: 10 * 60 * 1000 (10 dəqiqə) qoy. Lazımsız request-lər azalacaq, UX sürətlənəcək.


DevTools — Ən yaxşı dostun

React Query-nin öz DevTools-u var və bu, debug üçün əvəzsizdir:

bash
npm install @tanstack/react-query-devtools
jsx
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; function App() { return ( <QueryClientProvider client={queryClient}> <YourApp /> <ReactQueryDevtools initialIsOpen={false} /> </QueryClientProvider> ); }

Browser-da aşağı sol küncdə çiçək ikonu görəcəksən. Onu açsan, bütün query-lərin statusunu — fresh, stale, fetching, inactive — real vaxtda görəcəksən. Müsahibədə bunu bilmək xal qazandırır.


Rəqəmlərlə danışaq

npm tendensiyalarına görə, @tanstack/react-query həftədə 4.5 milyondan çox yüklənir (mart 2026). GitHub-da 43,000+ star var. Stack Overflow Developer Survey 2025-ə görə, React developer-lərin 38%-i artıq layihələrində TanStack Query istifadə edir.

Bakı kontekstinə gəlsək: LinkedIn-dəki iş elanlarına baxsanız, ABB, Kapital Bank texnoloji komandaları, Pasha Holding-in digital layihələri, aicgroup.az kimi şirkətlər artıq React ekosistemində işləyir. "TanStack Query" və ya "React Query" bilmək, 2000-3500 AZN diapazonundakı frontend maaşlarına namizəd olarkən sizi fərqləndirən bacarıqlardan biridir.


Redux ilə müqayisə — nə vaxt nə istifadə etməli?

  • Server state (API data, sifariş siyahısı, istifadəçi profili) → React Query
  • Client state (modal açıq/bağlı, sidebar vəziyyəti, form state) → Zustand və ya Redux Toolkit

Bir çox layihədə Redux-un 70%-i server state üçün istifadə olunurdu. React Query ilə o 70%-i silə bilərsən. Nəticədə store sadələşir, boilerplate azalır, developer experience artır.


Yekun məsləhətlər

  1. Yeni layihəyə başlayırsan? — React Query-ni 1-ci gündən qur
  2. Mövcud layihədə Redux-da API çağırışların var? — tədricən miqrasiya et, bir endpoint ilə başla
  3. queryKey-ləri düzgün strukturlaşdır['orders', { status, page }] kimi nested key-lər istifadə et
  4. staleTime-ı layihəyə uyğun tənzimlə — hər şey üçün defolt 0 saxlama
  5. DevTools-u development-də həmişə aktiv saxla

React Query öyrənmək bir axşama başa gəlir, amma layihəndəki kodu həftələrlə sadələşdirir. Bu gün npm install @tanstack/react-query yaz və fərqi özün gör.

Kod yazmağa davam et, Baku Stack seninlədir. 🚀

Oxşar məqalələr

react.ascii
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓ ■ ■ ■ REACT PERF ▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓ useMemo → cache ▓
▓ useCallback → ref ▓
▓░░░░░░░░░░░░░░░░░░░░░░▓
▓ 10K items: ▓
▓ no memo: 12ms ● ▓
▓ w/ memo: 0.3ms ✓ ▓
▓░░░░░░░░░░░░░░░░░░░░░░▓
▓ QAYDA: ▓
▓ >2ms → useMemo ✓ ▓
▓ <2ms → skip → ▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

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.ascii
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓ ■ ■ ■ REACT QUERY ▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓ useQuery('products') ▓
▓ ● status: success ▓
▓ ● stale: false ▓
▓ ● cache: 5m ▓
▓ ░░░░░░░░░░░░░░░░░░░░ ▓
▓ fetch ▓▓▓▓▓▓▓▓░░ 80% ▓
▓ cache ▓▓▓▓▓▓▓▓▓▓ ✓ ▓
▓ retry ▓▓░░░░░░░░ 1/3 ▓
▓ ░░░░░░░░░░░░░░░░░░░░ ▓
▓ → useState ✗ useQ ✓ ▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

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.ascii
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓ ■ ■ ■ REACT / RSC ▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓ Server Component: ▓
▓ fetch → render → HTML▓
▓ JS bundle: ░░░░ 0KB ▓
▓ Client Component: ▓
▓ useState ● onClick ▓
▓ JS bundle: ▓▓▓▓ 48KB ▓
▓ ──────────────────── ▓
▓ ✓ Data → Server ▓
▓ ✓ Event → Client ▓
▓ → Hybrid = Optimal ● ▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

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.

← Bloqa qayıt