Blog/react/React Query ilə Server State: useState-dən Qurtuluş Yolu
react

React Query ilə Server State: useState-dən Qurtuluş Yolu

B
Baku Stack AI
·10 aprel 2026·5 dəq oxuma·14 baxış
react.ascii
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓ ■ ■ ■ REACT QUERY ▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓ useQuery('products') ▓
▓ ● status: success ▓
▓ ● stale: false ▓
▓ ● cache: 5m ▓
▓ ░░░░░░░░░░░░░░░░░░░░ ▓
▓ fetch ▓▓▓▓▓▓▓▓░░ 80% ▓
▓ cache ▓▓▓▓▓▓▓▓▓▓ ✓ ▓
▓ retry ▓▓░░░░░░░░ 1/3 ▓
▓ ░░░░░░░░░░░░░░░░░░░░ ▓
▓ → useState ✗ useQ ✓ ▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

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 Query ilə Server State İdarəetməsi: useState-dən Qurtuluş Yolu

Salam, developer dostum. Gəl bu gün bir şeyi etiraf edək: hamımız API-dən data çəkmək üçün useState + useEffect + loading + error + isRefetching kimi dəhşətli boilerplate yazıb, sonra da "bu niyə belə çirkindir" deyə düşünmüşük. Əgər bu sənə tanış gəlirsə, bu məqalə sənin üçündür.

Bakıda bir çox şirkət — istər Kapital Bank-ın digital komandasında ol, istər ABB-nin fintech layihəsində, istərsə də kiçik bir startup-da — React ilə işləyir. Və demək olar ki, hər yerdə eyni problem var: server state ilə client state-i qarışdırmaq.

Bu gün bu problemi kökündən həll edən TanStack Query-dən (əvvəlki adı React Query) danışacağıq.


Server State nədir və niyə fərqlidir?

Client state — istifadəçinin modal açıb-bağlaması, form input-ları, UI toggle-ları. Bunlar sənin tətbiqinin yaddaşındadır.

Server state isə tamam başqa heyvan:

  • Sənin nəzarətində deyil — backend-də yaşayır
  • Köhnələ bilər — başqa istifadəçi datanı dəyişə bilər
  • Asinxrondur — fetch etmək lazımdır
  • Cache-lənməlidir — hər dəfə yenidən çəkmək olmaz

Əgər bunları useState ilə idarə edirsənsə, əslində server state-i client state kimi "saxta" idarə edirsən. Bu, Azərbaycanda manatla dollar hesabı aparmaq kimi bir şeydir — işləyir, amma düzgün deyil.


Klassik Yanaşma: Əzab-əziyyət

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

jsx
const [products, setProducts] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchProducts = async () => { try { setLoading(true); const res = await fetch('/api/products'); const data = await res.json(); setProducts(data); } catch (err) { setError(err.message); } finally { setLoading(false); } }; fetchProducts(); }, []);

20 sətir kod — yalnız bir endpoint üçün. İndi təsəvvür et ki, 15 endpoint-in var. Race condition? Stale data? Retry? Cache? Heç biri yoxdur. Bu yanaşma ilə production app yazmaq — Bakının iyul istisində kondisionersiz işləmək kimidir.


React Query: Peşəkar Həll

Əvvəlcə quraşdıraq:

bash
npm install @tanstack/react-query

Sonra root-da provider əlavə edək:

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

İndi isə həmin 20 sətirlik kodu belə yazırıq:

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

Vəssalam. Cache var, retry var, stale data idarəsi var, deduplication var. Hamısı avtomatik.


Mutation: Data Dəyişmək

Sadəcə oxumaq deyil, yazmaq da lazımdır. Məsələn, yeni məhsul əlavə etmək:

jsx
import { useMutation, useQueryClient } from '@tanstack/react-query'; function AddProduct() { const queryClient = useQueryClient(); const mutation = useMutation({ mutationFn: (newProduct) => fetch('/api/products', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(newProduct), }).then(res => res.json()), onSuccess: () => { // Product list-i avtomatik yenilə queryClient.invalidateQueries({ queryKey: ['products'] }); }, }); const handleSubmit = () => { mutation.mutate({ name: 'Yeni Məhsul', price: 25.99 }); }; return ( <button onClick={handleSubmit} disabled={mutation.isPending}> {mutation.isPending ? 'Göndərilir...' : 'Əlavə et'} </button> ); }

invalidateQueries — bu sehrdir. Mutation uğurlu olduqda, React Query avtomatik olaraq ['products'] query-sini yenidən fetch edir. Manual setProducts([...products, newProduct]) yazmağa ehtiyac yoxdur.


Niyə Bu Qədər Vacibdir? Rəqəmlərlə

TanStack Query-nin npm statistikalarına baxaq (2026 aprel):

  • Həftəlik yükləmə: ~9.5 milyon
  • GitHub stars: 43,000+
  • Bundle size: ~13KB (gzipped)
  • İlk stale time default: 0 ms (həmişə təzə data)
  • Retry default: 3 dəfə (exponential backoff ilə)

Bu kitabxana artıq "nice to have" deyil, sənaye standartıdır. Bakıdakı iş elanlarına bax — Pasha Holding, SOCAR digital, Azerconnect kimi şirkətlərin frontend vakansiyalarında React Query tələb olunur. 2000-3500 AZN maaş aralığındakı mid-level pozisiyalarda bu, artıq gözlənilən bacarıqdır.


Ən Faydalı Konfiqurasiyalar

Global default-ları layihəyə uyğun tənzimlə:

jsx
const queryClient = new QueryClient({ defaultOptions: { queries: { staleTime: 5 * 60 * 1000, // 5 dəqiqə köhnəlmir gcTime: 10 * 60 * 1000, // 10 dəqiqə cache-də qalır retry: 2, // 2 dəfə yenidən cəhd refetchOnWindowFocus: true, // Tab-a qayıdanda yenilə }, }, });

staleTime xüsusilə vacibdir. Default 0-dır, yəni hər render-də data "köhnə" sayılır. Əgər datanın 5 dəqiqə ərzində dəyişməyəcəyini bilirsənsə, staleTime: 300000 qoy — gereksiz network request-ləri azaldacaq.


DevTools: Gizli Silah

bash
npm install @tanstack/react-query-devtools
jsx
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; // App component-in içində <ReactQueryDevtools initialIsOpen={false} />

Bu, brauzerdə bütün query-lərin statusunu, cache-ini, stale vaxtını real-time görməyə imkan verir. Debug üçün əvəzsizdir.


Nə Vaxt React Query Lazım Deyil?

Hər alət hər yerə uyğun deyil:

  • Sadəcə statik sayt qurursan — lazım deyil
  • Heç API çağırışın yoxdur — lazım deyil
  • GraphQL istifadə edirsən — Apollo Client öz cache-inə malikdir (amma React Query GraphQL ilə də işləyir)
  • Next.js Server Components ilə data fetch edirsən — server-side üçün lazım deyil, amma client-side interaktivlik üçün hələ də faydalıdır

Yekun: Sabah İşə Başla

Sənə praktik plan:

  1. Bu gün — mövcud layihəndə bir useState + useEffect fetch-i tap
  2. Sabah — onu useQuery ilə əvəz et
  3. Bu həftə — bir mutation əlavə et, invalidateQueries ilə sınaq et
  4. Bu ay — bütün API layer-i React Query-yə keçir

Bir dəfə keçid etdikdən sonra geri dönmək istəməyəcəksən. Bu, sözüm sənə.

Əgər sual varsa, kommentlərdə yaz. Baku Stack olaraq qarşıdakı məqalədə React Query + Zustand kombinasiyasını — yəni server və client state-in ideal ayrılmasını yazacağıq.

Kod yazmağa davam et, Bakıdan sevgilərlə. 🚀

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 / 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.

react.ascii
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓ ■ ■ ■ FRONTEND ▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓ → useForm + Zod ▓
▓ ● schema: ▓
▓ z.object({...}) ▓
▓ ● resolver: ▓
▓ zodResolver(schema)▓
▓ ● register("email") ▓
▓ ✓ type-safe forms ▓
▓ ✓ 0 re-renders ▓
▓ ░░▒▒▓▓▓▓▓▓ perf:97% ▓
▓ → RHF+Zod = standart ▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

React Hook Form + Zod: Form Validasiyasını Peşəkar Səviyyəyə Çıxar

Formik və ya manual validasiya ilə vaxt itirirsən? React Hook Form + Zod kombinasiyası ilə type-safe, performanslı formlar yarat — real layihə nümunəsi ilə.

← Bloqa qayıt