Mundarija (34)
- Bu darsda
- 1. Nega bu kerak?
- 2. Qo'lda yozilgan so'rov va uning narxi
- 2.1 useEffect bilan yuklash
- 2.2 Nima yetishmaydi
- 3. Birinchi useQuery
- 3.1 O'rnatish va QueryClientProvider
- 3.2 O'sha menyu — useQuery bilan
- 3.3 queryKey — ma'lumotning nomi
- 3.4 queryFn — ma'lumotni qanday olish
- 4. Holatlar: isPending, isError, data
- 4.1 Uch holat
- 4.2 retry — qayta urinish
- 4.3 TypeScript: data doim ham bor emas
- 5. status va fetchStatus
- 5.1 Ikki savol, ikki maydon
- 5.2 paused — internet yo'q
- 6. Hujumchi nigohi: server javobiga ishonmang
- 7. Vazifalar qadami: server state — TanStack Query'da (holat 14 boshlanishi)
- 7.1 Reja
- 7.2 Provider: main.tsx
- 7.3 QueryClient: server-sinxron.ts
- 7.4 Hook: useVazifalar
- 7.5 Komponentlar: App.tsx va statistika
- 7.6 Narxi
- 8. Ko'p uchraydigan xatolar
- 9. Mashqlar
- 1-mashq (oson): holatni toping
- 2-mashq (o'rta): qo'lda yozilganini useQuery ga
- 3-mashq (qiyin): stol buyurtmasi va to'g'ri holatlar
- 4-mashq: Vazifalar qadami
- 10. Real ishda
- Xulosa
- Manbalar
TanStack Query useQuery: server ma'lumotini olish, keshlash va holatlar
Qisqacha:
useQuery({ queryKey: ["menyu"], queryFn: menyuniOl })— serverdan ma'lumot olishning tayyor usuli. Siz faqat ikki narsani berasiz: kalit (bu ma'lumotning nomi) va funksiya (uni qanday olish). Yuklanish, xato, keshlash va qayta urinishni TanStack Query o'zi qiladi. Bir xil kalitli ikki komponent serverga bitta so'rov yuboradi va natijani birga ko'radi.
Bu darsda
- Qo'lda yozilgan
useEffect+fetchkodida nima yetishmasligini sanab chiqasiz. QueryClient,QueryClientProvidervauseQuerybilan birinchi so'rovni yozasiz.queryKeyvaqueryFnqoidalarini bilasiz: kalit — massiv, funksiya — Promise.status(ma'lumot bormi?) vafetchStatus(hozir so'rov ketyaptimi?) farqini ajratasiz.vazifalarda 17–18-qismdagi qo'lda yozilgan yuklash kodiniuseQueryga almashtirishni boshlaysiz.
Oldin bilishingiz kerak: Server state vs client state, API qatlami va type-safe kontrakt, Effektda ma'lumot olish, useEffect III: cleanup va AbortController.
1. Nega bu kerak?
Server state vs client state darsida vazifalar ni o'lchadik. Yetti qadamda serverga to'rtta GET ketdi: ro'yxat sahifasiga har qaytishda qayta so'rov. Statistika esa serverga umuman so'ramasdi. Boshqa qurilmada vazifa qo'shilsa, sahifa yangilansa ham statistika eski raqamni ko'rsatardi: serverda 4, ekranda 3.
Bu ikki xato bitta sababdan. Server ma'lumoti har komponentda alohida yuklanadi va alohida saqlanadi. Ro'yxat o'zinikini, statistika o'zinikini. Ular bir-birini bilmaydi.
«Bahor» da ham shunday. Sardor sayt uchun uchta komponent yozdi: menyu ro'yxati, "bugun nechta taom bor" hisoblagichi va bosh sahifadagi "eng arzon taom". Uchalasi ham menyuni serverdan oladi. Natija — uchta bir xil so'rov va uchta "Yuklanmoqda…".
Hayotiy o'xshatish: oshxonadagi menyu doskasi. Ofitsiant har mehmon so'raganda oshpazdan "bugun nima bor?" deb so'ramaydi. Oshpaz menyuni doskaga bir marta yozadi, hamma ofitsiant doskaga qaraydi. Menyu o'zgarsa — doska yangilanadi. TanStack Query — ana shu doska: server ma'lumotining bitta umumiy nusxasi, uni kim so'rasa, o'sha ko'radi.
2. Qo'lda yozilgan so'rov va uning narxi
2.1 useEffect bilan yuklash
Effektda ma'lumot olish darsida shunday kod yozgan edik. Natija oynasida tarmoq yo'q, shuning uchun fetchMenu — soxta server: 200 ms dan keyin menyuni qaytaradi.
import { useEffect, useState } from "react";
function fetchMenu() {
console.log("so'rov ketdi");
return new Promise((resolve) =>
setTimeout(() => resolve(["Osh", "Lag'mon", "Manti"]), 200),
);
}
function Menu() {
const [menu, setMenu] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
let ignore = false;
fetchMenu()
.then((data) => {
if (!ignore) setMenu(data);
})
.catch((err) => {
if (!ignore) setError(err);
})
.finally(() => {
if (!ignore) setLoading(false);
});
return () => {
ignore = true;
};
}, []);
if (loading) return <p>Yuklanmoqda…</p>;
if (error) return <p>Xato: {error.message}</p>;
return <p>{menu.join(", ")}</p>;
}
export default function App() {
return (
<>
<Menu />
<Menu />
</>
);
}Konsolda:
so'rov ketdi
so'rov ketdiEkranda:
Osh, Lag'mon, Manti
Osh, Lag'mon, MantiKod ishlaydi. Lekin Menu ikki joyda turibdi va serverga ikkita so'rov ketdi. Uchta useState, ignore bayrog'i, uchta if — bularning hammasi bitta ro'yxat uchun.
2.2 Nima yetishmaydi
Bu kod hali "yaxshi" emas. Unda quyidagilar yo'q:
| Kerak | Qo'lda kodda |
|---|---|
| bir xil ma'lumotga bitta so'rov | har komponent o'zi so'raydi |
| sahifaga qaytganda darhol ko'rsatish | har safar "Yuklanmoqda…" |
| xatoda qayta urinish | yo'q |
| internet qaytganda yangilash | yo'q |
| boshqa joyda o'zgarsa, eskirganini bilish | yo'q |
Har birini qo'lda qo'shish mumkin. vazifalar da 17–18-qismlarda aynan shunday qildik: AbortController pulti, "kutilmoqda" hisobi, alohida tarmoq holati, online hodisasi. Fayl 158 qatorga yetdi va baribir statistika sahifasi eskirgan raqam ko'rsatardi. Shu ishni har loyihada qaytadan yozmaslik uchun kutubxona bor.
3. Birinchi useQuery
3.1 O'rnatish va QueryClientProvider
TanStack Query — server ma'lumotini olish, keshlash va yangilash uchun kutubxona. Avval "React Query" deb atalardi. Bugun u faqat React uchun emas (Vue, Solid, Svelte ham bor), shuning uchun nomi o'zgargan. React paketi — @tanstack/react-query. Kursda 5.104.1 versiyasi:
npm i --save-exact @tanstack/react-query@5.104.1Ishlatishdan oldin ikki narsa kerak:
QueryClient— kesh va sozlamalar saqlanadigan obyekt. O'xshatishimizdagi doska shu. Ilova uchun bitta yaratiladi, odatda modul darajasida.QueryClientProvider— shu obyektni butun daraxtga Context orqali beradi (Context I darsidagi g'oya). Ichidagi har komponentuseQuerychaqira oladi.
// main.jsx — o'z loyihangizda
import { createRoot } from "react-dom/client";
import {
QueryClient,
QueryClientProvider,
} from "@tanstack/react-query";
import { App } from "./App.jsx";
const queryClient = new QueryClient();
createRoot(document.getElementById("root")).render(
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>,
);3.2 O'sha menyu — useQuery bilan
Endi «Qo'lda yozilgan so'rov» bo'limidagi misolni qayta yozamiz. Natija oynasida har misol o'z QueryClient ini yaratadi va App ichida Provider qo'yadi:
import {
QueryClient,
QueryClientProvider,
useQuery,
} from "@tanstack/react-query";
const queryClient = new QueryClient();
function fetchMenu() {
console.log("so'rov ketdi");
return new Promise((resolve) =>
setTimeout(() => resolve(["Osh", "Lag'mon", "Manti"]), 200),
);
}
function Menu() {
const query = useQuery({
queryKey: ["menu"],
queryFn: fetchMenu,
});
if (query.isPending) return <p>Yuklanmoqda…</p>;
if (query.isError) return <p>Xato: {query.error.message}</p>;
return <p>{query.data.join(", ")}</p>;
}
export default function App() {
return (
<QueryClientProvider client={queryClient}>
<Menu />
<Menu />
</QueryClientProvider>
);
}Konsolda:
so'rov ketdiEkranda:
Osh, Lag'mon, Manti
Osh, Lag'mon, MantiUchta useState, effekt va ignore yo'qoldi. Eng muhimi — konsolda bitta "so'rov ketdi". Ikkinchi Menu ham ["menu"] kalitini so'radi. Query bu kalit uchun so'rov allaqachon ketayotganini ko'rdi va yangisini yubormadi. Ikkalasi bitta javobni kutdi. Buni takroriy so'rovlarni birlashtirish (deduplication) deyishadi.
Qatorma-qator nima bo'ldi:
| Vaqt | Keshda ["menu"] |
Ekranda |
|---|---|---|
| 0 ms | yo'q → so'rov ketdi | ikki marta "Yuklanmoqda…" |
0 ms (2-Menu) |
so'rov yo'lda — kutadi | "Yuklanmoqda…" |
| 200 ms | ["Osh", "Lag'mon", "Manti"] |
ikki marta menyu |
useQuery qaytargan obyektda ko'p maydon bor. Hozircha uchtasi kerak: isPending (ma'lumot hali yo'q), isError (so'rov yiqildi), data (ma'lumotning o'zi).
Butun jarayon rasmda. Komponentlar serverga emas, keshga murojaat qiladi. Serverga faqat kesh boradi:
flowchart LR
A["Menu (1)"] -->|"['menu']"| K["QueryClient keshi"]
B["Menu (2)"] -->|"['menu']"| K
K -->|"yo'q bo'lsa: queryFn"| S["Server"]
S -->|"javob"| K
K -->|"data"| A
K -->|"data"| B3.3 queryKey — ma'lumotning nomi
So'rov kaliti (query key) — keshdagi ma'lumotni topish uchun nom. U doim massiv: ["menu"], ["dish", "osh"], ["orders", { table: 4 }].
Qoidalar:
- Bir xil kalit — bir xil ma'lumot. Ikki komponent
["menu"]desa, ular bitta keshni ko'radi. - Funksiya nimaga bog'liq bo'lsa, o'sha qiymat kalitda bo'ladi.
fetchDish(slug)uchun kalit —["dish", slug]. Aks holda osh va manti bitta kesh joyiga tushadi. - Kalit JSON'ga aylana oladigan qiymatlardan tuziladi: satr, son, massiv, oddiy obyekt. Obyektdagi kalitlar tartibi ahamiyatsiz —
{ a: 1, b: 2 }va{ b: 2, a: 1 }bir xil kalit.
Kalit o'zgarsa, Query uni boshqa so'rov deb biladi. Taom tanlaganda shu bo'ladi:
import { useState } from "react";
import {
QueryClient,
QueryClientProvider,
useQuery,
} from "@tanstack/react-query";
const queryClient = new QueryClient();
const PRICES = { osh: 35000, manti: 30000 };
function fetchPrice(slug) {
console.log("so'rov:", slug);
return new Promise((resolve) =>
setTimeout(() => resolve(PRICES[slug]), 200),
);
}
function Price({ slug }) {
const { isPending, data } = useQuery({
queryKey: ["price", slug],
queryFn: () => fetchPrice(slug),
});
if (isPending) return <p>Yuklanmoqda…</p>;
return <p>{slug}: {data} so'm</p>;
}
function Dishes() {
const [slug, setSlug] = useState("osh");
return (
<>
<button onClick={() => setSlug("osh")}>Osh</button>{" "}
<button onClick={() => setSlug("manti")}>Manti</button>
<Price slug={slug} />
</>
);
}
export default function App() {
return (
<QueryClientProvider client={queryClient}>
<Dishes />
</QueryClientProvider>
);
}Konsolda:
so'rov: osh
so'rov: manti
so'rov: oshEkranda («Osh» bosilgandan 100 ms keyin):
Osh Manti
osh: 35000 so'm«Manti» bosilganda kalit ["price", "manti"] ga o'zgardi — yangi so'rov, yangi "Yuklanmoqda…". «Osh» ga qaytganda esa "Yuklanmoqda…" yo'q: narx 100 ms da, ya'ni javob kelishidan oldin ekranda. ["price", "osh"] keshda turgan edi. Eski kalitning ma'lumoti yo'qolmaydi.
Lekin konsolning uchinchi qatoriga qarang: so'rov: osh yana bor. Query keshdagini darhol ko'rsatdi va fonda serverdan yangisini so'radi — ehtiyot uchun. Bu qachon kerak va qachon ortiqcha — keyingi darsda staleTime bilan hal qilamiz.
3.4 queryFn — ma'lumotni qanday olish
So'rov funksiyasi (query function) — ma'lumotni olib keladigan funksiya. Ikki qoida bor:
- Promise qaytaradi. Muvaffaqiyat — Promise qiymat bilan bajariladi (resolve). Xato — xato tashlaydi (reject yoki
throw). Query xatoni shu yo'l bilan biladi. undefinedqaytarmaydi. "Ma'lumot yo'q" bo'lsa —nullyoki bo'sh massiv qaytaring.
Ikkinchi qoidani buzish oson. Funksiya ichida return ni unutish kifoya:
import {
QueryClient,
QueryClientProvider,
useQuery,
} from "@tanstack/react-query";
const queryClient = new QueryClient({
defaultOptions: { queries: { retry: false } },
});
function fetchMenu() {
// return yo'q — funksiya undefined qaytaradi
new Promise((resolve) => setTimeout(() => resolve(["Osh"]), 100));
}
function Menu() {
const query = useQuery({ queryKey: ["menu"], queryFn: fetchMenu });
return <p>Holat: {query.status}</p>;
}
export default function App() {
return (
<QueryClientProvider client={queryClient}>
<Menu />
</QueryClientProvider>
);
}Konsolda:
Query data cannot be undefined. Please make sure to return a value other than undefined from your query function. Affected query key: ["menu"]Ekranda:
Holat: errorTarjimasi: "So'rov ma'lumoti undefined bo'la olmaydi. So'rov funksiyasidan undefined dan boshqa qiymat qaytaring. Kalit: ["menu"]." Query undefined ni "ma'lumot hali yo'q" belgisi sifatida ishlatadi. Shuning uchun u buni xato deb hisoblaydi. Xabar faqat dev rejimida konsolga chiqadi, production'da faqat status: "error" qoladi.
Funksiyaga Query bitta argument beradi — kontekst obyekti. Unda queryKey va signal bor. signal — AbortController darsidagi bekor qilish signali: so'rov kerak bo'lmay qolsa, Query uni bekor qiladi. To'liq — TanStack Query V darsida. Haqiqiy loyihada queryFn odatda shunday ko'rinadi:
const query = useQuery({
queryKey: ["dish", slug],
queryFn: async ({ signal }) => {
const res = await fetch(`/api/dishes/${slug}`, { signal });
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json();
},
});if (!res.ok) throw ni unutmang. fetch asoslari darsidan eslang: fetch 404 va 500 da xato tashlamaydi. Bu qatorsiz Query xato sahifasini "muvaffaqiyat" deb saqlaydi.
Tekshirib ko'ring: Ikki komponent: biri
["dish", "osh"], ikkinchisi["dish", "manti"]so'raydi. Ular bir vaqtda chiziladi. Serverga nechta so'rov ketadi?
Javob
Ikkita. Kalitlar har xil, demak bu ikki xil ma'lumot. Birlashtirish faqat aynan bir xil kalitda ishlaydi. Agar ikkalasi ham ["dish", "osh"] desa — bitta so'rov bo'lardi.
4. Holatlar: isPending, isError, data
4.1 Uch holat
useQuery natijasida status maydoni bor. U ma'lumot haqida gapiradi va uch qiymatdan birini oladi:
status |
Qisqasi | Ma'nosi |
|---|---|---|
"pending" |
isPending |
ma'lumot hali yo'q |
"error" |
isError |
so'rov yiqildi, error da sababi |
"success" |
isSuccess |
ma'lumot bor, data da |
Komponentda tekshirish tartibi odatda shunday: avval isPending, keyin isError, oxirida data. Ikkala if dan o'tgach data aniq bor.
Xatoni ko'ramiz. Soxta server bu safar rad etadi:
import {
QueryClient,
QueryClientProvider,
useQuery,
} from "@tanstack/react-query";
const queryClient = new QueryClient({
defaultOptions: { queries: { retry: false } },
});
function fetchMenu() {
return new Promise((_, reject) =>
setTimeout(() => reject(new Error("Server javob bermadi")), 200),
);
}
function Menu() {
const { isPending, isError, error, data } = useQuery({
queryKey: ["menu"],
queryFn: fetchMenu,
});
if (isPending) return <p>Yuklanmoqda…</p>;
if (isError) return <p>Xato: {error.message}</p>;
return <p>{data.join(", ")}</p>;
}
export default function App() {
return (
<QueryClientProvider client={queryClient}>
<Menu />
</QueryClientProvider>
);
}Ekranda:
Xato: Server javob bermadiQueryClient ga retry: false berdik. Nega — keyingi bo'limda.
4.2 retry — qayta urinish
Sukut bo'yicha Query yiqilgan so'rovni 3 marta qayta sinaydi. Oralar o'sib boradi: 1 s, 2 s, 4 s. Ya'ni xato ekranga taxminan 7 sekunddan keyin chiqadi. Tarmoq bir zumga uzilgan bo'lsa, foydalanuvchi buni sezmaydi ham — bu yaxshi. Lekin server aniq "yo'q" desa, 7 sekund "Yuklanmoqda…" ko'rsatish yomon.
Qayta urinishni ko'ramiz. Natija oynasida uzoq kutmaslik uchun oraliqni 200 ms qildik (retryDelay):
import {
QueryClient,
QueryClientProvider,
useQuery,
} from "@tanstack/react-query";
const queryClient = new QueryClient();
let attempt = 0;
function fetchMenu() {
attempt += 1;
console.log("urinish", attempt);
return Promise.reject(new Error("Server javob bermadi"));
}
function Menu() {
const query = useQuery({
queryKey: ["menu"],
queryFn: fetchMenu,
retry: 2,
retryDelay: 200,
});
return (
<p>
{query.status}, xatolar: {query.failureCount}
</p>
);
}
export default function App() {
return (
<QueryClientProvider client={queryClient}>
<Menu />
</QueryClientProvider>
);
}Konsolda:
urinish 1
urinish 2
urinish 3Ekranda:
error, xatolar: 3retry: 2 — birinchi urinish va yana ikkitasi, jami uch. failureCount — nechta urinish yiqilgani. Urinishlar davomida status — "pending", oxirgisidan keyingina "error".
retry ni qayerda sozlash:
false— bitta urinish. Testlarda va natija oynasidagi misollarda doim shunday (aks holda xato misoli 7 s kutadi).vazifalarda ham — sababi «Vazifalar qadami» bo'limida.- son — nechta qayta urinish.
- funksiya — sharti bilan:
retry: (count, error) => error.status !== 404 && count < 3. 404 — "bunday narsa yo'q", qayta so'rash befoyda.
4.3 TypeScript: data doim ham bor emas
TypeScript'da data turi queryFn dan olinadi. Promise<string[]> qaytarsa — data turi string[] | undefined. undefined — chunki isPending da hali ma'lumot yo'q. Tekshirmasdan ishlatsak, kompilyator to'xtatadi:
import { useQuery } from "@tanstack/react-query";
function fetchMenu(): Promise<string[]> {
return Promise.resolve(["Osh", "Manti"]);
}
export function Menu() {
const query = useQuery({ queryKey: ["menu"], queryFn: fetchMenu });
return <p>{query.data.length} ta taom</p>;
}Xato:
TS18048: 'query.data' is possibly 'undefined'.Tarjimasi: "query.data undefined bo'lishi mumkin". Davosi — avval holatni tekshirish. if (query.isPending) return … dan keyin TypeScript data ni string[] deb biladi. Bu Discriminated union darsidagi toraytirish: status — ajratuvchi maydon.
Tekshirib ko'ring:
retry: 3va sukutdagi oraliqlar (1 s, 2 s, 4 s) bilan server doim yiqilsa,queryFnnecha marta chaqiriladi va xato qachon ekranga chiqadi?
Javob
To'rt marta: bitta asosiy urinish va uchta qayta urinish. Xato ~7 s dan keyin chiqadi (1 + 2 + 4). Shu vaqt davomida status — "pending", ekranda "Yuklanmoqda…". Shuning uchun aniq javob beradigan xatolarda (404, 403) retry ni funksiya bilan cheklash kerak.
5. status va fetchStatus
5.1 Ikki savol, ikki maydon
status faqat bitta savolga javob beradi: ma'lumot bormi? Lekin ikkinchi savol ham bor: hozir so'rov ketyaptimi? Ma'lumot ekranda turgan paytda ham Query fonda uni yangilashi mumkin. Buning uchun alohida maydon — fetchStatus:
fetchStatus |
Qisqasi | Ma'nosi |
|---|---|---|
"fetching" |
isFetching |
queryFn hozir ishlayapti |
"paused" |
isPaused |
so'rov kerak, lekin internet yo'q — kutyapti |
"idle" |
— | hech narsa qilinmayapti |
Ikkalasi mustaqil. Masalan, status: "success" va fetchStatus: "fetching" — ma'lumot ekranda, orqada yangisi kelyapti. Buni ko'ramiz. «Yangilash» tugmasi refetch() ni chaqiradi — so'rovni qo'lda qayta yuboradi:
import {
QueryClient,
QueryClientProvider,
useQuery,
} from "@tanstack/react-query";
const queryClient = new QueryClient();
let count = 3;
function fetchCount() {
count += 1;
return new Promise((resolve) =>
setTimeout(() => resolve(count), 200),
);
}
function DishCount() {
const query = useQuery({
queryKey: ["count"],
queryFn: fetchCount,
});
console.log(query.status, query.fetchStatus, query.data);
if (query.isPending) return <p>Yuklanmoqda…</p>;
return (
<>
<p>
Bugun {query.data} ta taom
{query.isFetching && " (yangilanmoqda…)"}
</p>
<button onClick={() => query.refetch()}>Yangilash</button>
</>
);
}
export default function App() {
return (
<QueryClientProvider client={queryClient}>
<DishCount />
</QueryClientProvider>
);
}Konsolda:
pending fetching undefined
success idle 4
success fetching 4
success idle 5Ekranda:
Bugun 5 ta taom
YangilashKonsolning uchinchi qatoriga qarang: success fetching 4. Ekranda eski raqam (4) turibdi, yonida "(yangilanmoqda…)". "Yuklanmoqda…" ga qaytmadik — chunki isPending faqat birinchi yuklashda rost. Ma'lumot bir marta kelgandan keyin u har doim ekranda qoladi, yangisi kelguncha.
Qoida: butun sahifani almashtiradigan "Yuklanmoqda…" — isPending ga, kichik "yangilanmoqda" belgisi — isFetching ga bog'lanadi.
Ikki maydonni bitta rasmda ko'ramiz. Har katak — ikki holatning bir juftligi:
stateDiagram-v2
[*] --> A
A: pending + fetching (birinchi yuklash)
A --> B: javob keldi
A --> E: yiqildi
B: success + idle (ma'lumot ekranda)
B --> C: refetch
C: success + fetching (fonda yangilash)
C --> B: yangi javob
E: error + idle
E --> A: qayta urinish5.2 paused — internet yo'q
Uchinchi qiymat — "paused". Query brauzerdagi online/offline hodisalarini kuzatadi (navigator va qurilma API'lari darsidagi hodisalar). Internet yo'q bo'lsa, so'rovni yubormaydi va xato ham bermaydi — kutadi. Internet qaytishi bilan o'zi yuboradi.
Natija oynasida internetni o'chirib bo'lmaydi. Uning o'rniga Query'ning onlineManager idan foydalanamiz — u Query uchun "internet bormi?" degan savolga javob beradi. setOnline(false) — "yo'q" deb aytamiz:
import {
onlineManager,
QueryClient,
QueryClientProvider,
useQuery,
} from "@tanstack/react-query";
const queryClient = new QueryClient();
onlineManager.setOnline(false);
function fetchMenu() {
console.log("so'rov ketdi");
return Promise.resolve(["Osh", "Manti"]);
}
function Menu() {
const query = useQuery({ queryKey: ["menu"], queryFn: fetchMenu });
return (
<>
<p>
{query.status} / {query.fetchStatus}
</p>
<button onClick={() => onlineManager.setOnline(true)}>
Internet qaytdi
</button>
</>
);
}
export default function App() {
return (
<QueryClientProvider client={queryClient}>
<Menu />
</QueryClientProvider>
);
}Konsolda:
so'rov ketdiEkranda:
success / idle
Internet qaytdiTugmani bosishdan oldin ekranda pending / paused edi va konsol bo'sh edi: so'rov umuman ketmadi. Tugmadan keyin — bitta so'rov va success. 17-qismda vazifalar da shu xulqni online hodisasi bilan qo'lda yozgan edik.
Diqqat:
isPendingrost bo'lsa, so'rov ketyapti deb o'ylamang.pending + pausedham bor: ma'lumot yo'q va so'rov kutib turibdi. "Yuklanmoqda…" o'rniga "Internet yo'q — ulanish kutilmoqda" desangiz, foydalanuvchi aldanmaydi. Tekshiruv:isPending && isPaused.
Tekshirib ko'ring: Ekranda vazifalar ro'yxati turibdi. Foydalanuvchi «Yangilash» ni bosdi, lekin internet yo'q.
statusvafetchStatusqanday bo'ladi?
Javob
status: "success" (ma'lumot bor, ekranda qoladi) va fetchStatus: "paused" (so'rov kerak, internet kutilyapti). Ro'yxat yo'qolmaydi, xato ham chiqmaydi. Internet qaytganda so'rov o'zi ketadi.
6. Hujumchi nigohi: server javobiga ishonmang
queryFn qaytargan narsa to'g'ridan-to'g'ri keshga va ekranga tushadi. Query ma'lumotning shaklini tekshirmaydi. Server buzilgan bo'lsa yoki javob yo'lda almashtirilsa (soxta Wi-Fi, buzilgan proksi), noto'g'ri shakldagi ma'lumot ilovani yiqitishi mumkin.
API qatlami va type-safe kontrakt darsida vazifalar ga Zod sxemasini qo'ydik. queryFn — uni ishlatadigan to'g'ri joy: javob keshga tushishidan oldin tekshiriladi. Mos kelmasa — xato tashlanadi va Query uni oddiy xato kabi ko'rsatadi:
import {
QueryClient,
QueryClientProvider,
useQuery,
} from "@tanstack/react-query";
import * as z from "zod/mini";
const queryClient = new QueryClient({
defaultOptions: { queries: { retry: false } },
});
const DishSchema = z.object({
name: z.string(),
price: z.number(),
});
const MenuSchema = z.array(DishSchema);
// Server "buzilgan": narx son o'rniga matn
function fetchRaw() {
return Promise.resolve([
{ name: "Osh", price: 35000 },
{ name: "Manti", price: "<img src=x onerror=alert(1)>" },
]);
}
async function fetchMenu() {
const raw = await fetchRaw();
const result = MenuSchema.safeParse(raw);
if (!result.success) {
console.warn(result.error.issues[0].path.join("."));
throw new Error("Server javobi kutilgan shaklda emas");
}
return result.data;
}
function Menu() {
const { isPending, isError, error, data } = useQuery({
queryKey: ["menu"],
queryFn: fetchMenu,
});
if (isPending) return <p>Yuklanmoqda…</p>;
if (isError) return <p>Xato: {error.message}</p>;
return <p>{data.map((d) => d.name).join(", ")}</p>;
}
export default function App() {
return (
<QueryClientProvider client={queryClient}>
<Menu />
</QueryClientProvider>
);
}Konsolda:
1.priceEkranda:
Xato: Server javobi kutilgan shaklda emasKonsoldagi 1.price — qaysi maydon buzilgan: ikkinchi taomning (indeks 1) narxi. Hujumchi price ga HTML kod qo'ydi. React matnni baribir xavfsiz chiqarardi (Frontend xavfsizligi React'da). Lekin price * 2 kabi hisob NaN berardi, kesh esa buzuq ma'lumotni boshqa sahifalarga ham tarqatardi. Tekshiruv chegarada turadi: kirdi — tekshirildi — keshga tushdi.
Natija oynasida Zod faqat inglizcha xabar beradi, shuning uchun foydalanuvchiga ko'rinadigan matnni o'zimiz yozdik. vazifalar da api.ts aynan shunday qiladi: har metod tekshirilgan turni qaytaradi, mos kelmasa — ApiXatosi.
7. Vazifalar qadami: server state — TanStack Query'da (holat 14 boshlanishi)
7.1 Reja
Bu va keyingi ikki dars — bitta qadam. Kanonda ular bitta holatda (14) va bitta commit'da. Sababi: 17–18-qismdagi o'qish va yozish kodi bitta "xo'jalik" bilan bog'langan edi — AbortController pulti va "kutilmoqda" hisobi. Birini Query'ga ko'chirib, ikkinchisini eski holda qoldirib bo'lmaydi. Bugun — o'qish (useQuery), keyingi darsda — kesh qoidalari, undan keyingisida — yozish va commit.
git switch -c refactor/tanstack-query
npm i --save-exact @tanstack/react-query@5.104.1package.json da bitta qator qo'shiladi: "@tanstack/react-query": "5.104.1".
7.2 Provider: main.tsx
Kanon:
+import { QueryClientProvider } from "@tanstack/react-query";
import { createBrowserRouter, RouterProvider } from "react-router";
...
-import { xatoMatni } from "./server-sinxron.ts";
+import { sorovMijozi, xatoMatni } from "./server-sinxron.ts";
...
<AuthProvider>
- <RouterProvider router={router} />
+ {/* 19/#13: server holati keshi — hamma sahifa
+ uchun bitta (loader'lar ham shu sorovMijozi'ni
+ ishlatadi) */}
+ <QueryClientProvider client={sorovMijozi}>
+ <RouterProvider router={router} />
+ </QueryClientProvider>
</AuthProvider>Provider router'dan tashqarida. Shuning uchun har sahifa bitta keshni ko'radi: ro'yxat ham, statistika ham.
7.3 QueryClient: server-sinxron.ts
17-qismdan beri server bilan ishlaydigan hamma kod shu faylda. Endi uning yuragi — QueryClient. Kod kanondan aynan; bu va keyingi bloklarda izohlar telefonga sig'ishi uchun qisqa qatorlarga bo'lingan:
/**
* Ilovaning yagona QueryClient'i (main.tsx — Provider,
* loader'lar — to'g'ridan). Kesh qoidalari (19/#14,
* o'lchandi — natijalar/14-*):
* - staleTime 30 s: shu vaqt ichida qaytgan sahifa keshdan,
* so'rovsiz; undan keyin — keshdan DARHOL ko'rsatiladi va
* fonda yangilanadi
* - retry yo'q: v8 dagidek — server javob bermasa, darhol
* "xato" va «Qayta urinish» (sukutdagi 3 urinish ~7 s
* ekranni "yuklanmoqda" da ushlab turardi)
* - gcTime — sukut (5 daq): hech kim ishlatmagan kesh
* shundan keyin o'chadi
*/
export const sorovMijozi = new QueryClient({
defaultOptions: {
queries: { staleTime: 30_000, retry: false },
mutations: { retry: false },
},
});retry: false — «retry — qayta urinish» bo'limidagi sabab: vazifalar da «Qayta urinish» tugmasi bor, foydalanuvchi o'zi hal qiladi. staleTime va gcTime — keyingi darsning mavzusi.
So'rov kaliti va queryFn ning yuragi (kod izohidagi "kesh kaliti" — o'sha so'rov kaliti):
/** Kesh kaliti: shu brauzer ro'yxati (server kaliti bilan) */
export const royxatKaliti = ["vazifalar", kalitniOl()] as const;Kalitda kalitniOl() — shu brauzerning server kaliti (localStorage da). Ro'yxat shu kalitga bog'liq, demak u queryKey da turishi kerak — «queryKey — ma'lumotning nomi» bo'limidagi qoida.
queryFn — royxatniYukla. Ichida 17-qismdagi mantiq: server bu kalitni bilmasa (versiya === 0), brauzerdagi ro'yxat serverga yuboriladi (PUT). Yangisi — xato tashlash va signal:
async function royxatniYukla(
mijoz: QueryClient,
signal: AbortSignal,
): Promise<Vazifalar> {
let javob;
try {
javob = await api.royxat({ signal });
if (javob.versiya === 0) {
javob = await api.almashtir(joriyRoyxat(mijoz), { signal });
}
} catch (xato) {
// Ekranda — "xato" (so'rov holati); sababi — konsolda
// (bekor qilingani — xato emas: o'rniga yangisi ketdi
// yoki sahifa yopildi)
if (!signal.aborted) {
console.warn(`Sinxron bo'lmadi: ${xatoMatni(xato)}`);
}
throw xato;
}
// Farq bo'lsa — boshqa tablarga ham (ular serverga so'ramaydi)
if (
eksportMatni(javob.vazifalar) !== eksportMatni(joriyRoyxat(mijoz))
) {
tablargaYubor(javob.vazifalar);
}
return javob.vazifalar;
}catch ichida xato qayta tashlanadi (throw xato). Aks holda funksiya undefined qaytarardi — «queryFn — ma'lumotni qanday olish» bo'limidagi xato. api.royxat esa javobni Zod bilan tekshirib qaytaradi (API qatlami darsidagi sxema) — «Hujumchi nigohi» shu yerda ishlaydi.
7.4 Hook: useVazifalar
Komponentlar Query'ni to'g'ridan-to'g'ri emas, kichik custom hook orqali ishlatadi (Custom hooklar I). Ekrandagi aloqa holati ("yuklanmoqda", "xato", "tayyor") endi alohida state emas — so'rov holatidan hisoblanadi (kanon):
/**
* Ekrandagi aloqa holati — so'rov holatidan (alohida state
* yo'q)
*/
function tarmoqHolati(sorov: {
isError: boolean;
fetchStatus: "fetching" | "paused" | "idle";
dataUpdatedAt: number;
}): TarmoqHolati {
if (sorov.fetchStatus === "fetching" && sorov.dataUpdatedAt === 0) {
return "yuklanmoqda"; // hali bir marta ham serverdan kelmagan
}
if (sorov.isError) {
return sorov.fetchStatus === "fetching" ? "yuklanmoqda" : "xato";
}
return sorov.dataUpdatedAt === 0 ? "yuklanmoqda" : "tayyor";
}
/**
* Ro'yxat (server tasdiqlagan), aloqa holati va «Qayta
* urinish». boshlangich — kesh bo'sh bo'lsa (birinchi
* ochilish, testlar) shu ro'yxat
*/
export function useVazifalar(boshlangich?: Vazifalar) {
const mijoz = useQueryClient();
const sorov = useQuery({
...royxatSorovi(mijoz),
...(boshlangich === undefined ? {} : { initialData: boshlangich }),
});
return {
vazifalar: sorov.data,
tarmoq: tarmoqHolati(sorov),
qaytaUrin: () => void sorov.refetch(),
};
}Bugungi darsdan uch narsani taniysiz:
fetchStatus— "so'rov yo'ldami?".isError— "oxirgi urinish yiqildimi?".dataUpdatedAt— ma'lumot serverdan oxirgi marta qachon kelgan (0 — hali hech qachon).refetch()— «Qayta urinish» tugmasi. 17-qismdasinxronla(...)ni qo'lda chaqirardik.useQueryClient()— Provider berganQueryClientni oladi.
royxatSorovi(mijoz) — so'rov sozlamalari (kalit, queryFn va boshqalar) bitta funksiyada. Nega funksiya va initialData nima — keyingi darsda ochamiz.
7.5 Komponentlar: App.tsx va statistika
App.tsx da 17/#39 dagi useReducer ketdi. Unda ikki xil narsa aralashgan edi: server ro'yxati va "qaysi vazifa tahrirda". Birinchisi — Query'ga, ikkinchisi — oddiy useState ga (kanon):
- const [holat, dispatch] = useReducer(
- vazifalarReducer,
- boshlangichRoyxat,
- boshlangichHolat,
- );
- const { vazifalar: asosiy, tahrirId } = holat;
+ // 19/#13: SERVER holati — Query keshida (server-sinxron.ts):
+ // ro'yxat, aloqa holati, qayta urinish. 17/#39 dagi
+ // useReducer'da endi faqat mijoz (client) holati qolardi —
+ // tahrirdagi vazifa — u oddiy state
+ const mijoz = useQueryClient();
+ const {
+ vazifalar: asosiy,
+ tarmoq,
+ qaytaUrin,
+ } = useVazifalar(boshlangichRoyxat);
+ const yoz = useYozuv();
+ const [tahrirIdXom, setTahrirId] = useState<number | null>(null);Va 17/#28 dagi effekt butunlay o'chdi:
- useEffect(() => {
- void sinxronla(boshlangichRoyxat, { dispatch, setTarmoq, xojalik });
- return () => sinxronniTox(xojalik);
- }, [boshlangichRoyxat]);
+ // 17/#28 dagi "ochilganda serverdan" effekti va "online"
+ // hodisasi — 19/#13 dan Query'da (refetchOnMount,
+ // refetchOnReconnect). Internet uzildi — yo'ldagi so'rov
+ // endi kerak emas
+ useOynaHodisasi("offline", () => {
+ void mijoz.cancelQueries({ queryKey: royxatKaliti });
+ });const [tarmoq, setTarmoq] = useState(...) ham, xojalik ref'i ham ketdi. Tarmoq holati — so'rovning o'zida. useYozuv — mutatsiyalar darsida.
Statistika sahifasi — o'lchovdagi "eski 3" xatosining egasi. Endi u ham useVazifalar() ni chaqiradi (kanon):
-// StatistikaSahifasi.tsx — "/statistika" (19/#02). Ro'yxat —
-// shu brauzerdagi nusxadan (localStorage) …
+// StatistikaSahifasi.tsx — "/statistika" (19/#02). 19/#13:
+// ro'yxat — Query keshidan (ro'yxat sahifasi bilan bitta
+// kesh): 19/#02 da localStorage'dan o'qilardi va server bilan
+// hech solishtirilmasdi (o'lchandi:
+// natijalar/11-sorovlar-oldin.txt — serverda 4, ekranda 3)
...
- const [vazifalar] = useState(() => yukla() ?? boshlangichVazifalar);
+ const { vazifalar, tarmoq, qaytaUrin } = useVazifalar();Bitta qator — va statistika ro'yxat bilan bitta keshda. Ro'yxat sahifasida yuklangan ma'lumotni statistika qayta so'ramaydi. Statistikada ochilgan sahifa esa serverdan oladi. Natijani o'lchov bilan keyingi darsda ko'ramiz. Commit — mutatsiyalar darsida, yozish qismi ham ko'chgandan keyin.
7.6 Narxi
Kutubxona bepul emas. Build'da birinchi yuklanadigan JS+CSS (gzip) +9.9 KB o'sdi. 19-qism oxirigacha router (+29.4), formalar (+14.7 va +5.8) va Zustand (+1.3) bilan birga 84.6 KB dan ~153.7 KB ga chiqadi. Evaziga — 158 qatorli qo'lda yozilgan "xo'jalik" o'rniga sinalgan kutubxona va statistikadagi xatoning yo'qolishi.
8. Ko'p uchraydigan xatolar
Eng ko'p uchraydigani — Provider'ni unutish:
import { useQuery } from "@tanstack/react-query";
function Menu() {
const query = useQuery({
queryKey: ["menu"],
queryFn: () => Promise.resolve(["Osh"]),
});
return <p>{query.status}</p>;
}
export default function App() {
return <Menu />;
}Konsolda:
Uncaught Error: No QueryClient set, use QueryClientProvider to set oneTarjimasi: "QueryClient o'rnatilmagan, uni o'rnatish uchun QueryClientProvider ishlating". useQuery keshni Context'dan qidiradi va topmaydi. Ko'pincha testda uchraydi: komponent Provider'siz chiziladi. vazifalar testlari shuning uchun har testga o'z QueryClient ini beradi.
| Belgi | Sabab | Davosi |
|---|---|---|
No QueryClient set… |
Provider yo'q | ildizda QueryClientProvider |
Query data cannot be undefined… |
queryFn da return yo'q |
qiymat yoki null qaytaring |
| xato sahifasi "muvaffaqiyat" bo'lib keshda | fetch 404 da tashlamaydi |
if (!res.ok) throw … |
| xato 7 s dan keyin chiqadi | sukutdagi 3 qayta urinish | retry: false yoki shart bilan |
| osh va manti bir xil narx | kalitda slug yo'q |
queryKey: ["price", slug] |
| har render'da yangi so'rov, kesh bo'sh | new QueryClient() komponent ichida |
modul darajasida yoki useState(() => new QueryClient()) |
| "Yuklanmoqda…" internet yo'qda abadiy | pending + paused |
isPaused ni ham ko'rsating |
Oxirgisidan oldingisiga e'tibor bering. QueryClient ni App ichida const client = new QueryClient() deb yaratsangiz, har render'da yangi, bo'sh kesh paydo bo'ladi. vazifalar testlaridagi useState(() => new QueryClient(...)) — bir marta yaratishning React usuli (State I: useState dagi lazy init).
9. Mashqlar
Mashqlar kurs/mashqlar/19/13-usequery/ da. Har yechimni «Ishga tushir» bilan sinang.
1-mashq (oson): holatni toping
Har juftlik uchun ekranda nima bo'lishi kerak?
status: "pending",fetchStatus: "fetching"→status: "success",fetchStatus: "fetching"→ ma'lumot ekranda va fondastatus: "pending",fetchStatus: "paused"→ ma'lumot yo'q va kutilyaptistatus: "error",fetchStatus: "idle"→ xabari
Yechim
- Birinchi yuklash — butun joyda "Yuklanmoqda…".
- Eski ma'lumot ekranda qoladi, yonida kichik "yangilanmoqda" belgisi (
isFetching). - Ma'lumot ham yo'q, so'rov ham ketmayapti — internet kutilyapti (
isPaused). "Yuklanmoqda…" deyish noto'g'ri bo'lardi. - So'rov yiqildi va boshqa urinish yo'q — xato matni va «Qayta urinish».
2-mashq (o'rta): qo'lda yozilganini useQuery ga
Quyidagi komponent ichimliklar ro'yxatini useEffect bilan oladi. Uni useQuery ga o'tkazing:
- Kalit —
["drinks"], funksiya —fetchDrinks. isPendingda "Yuklanmoqda…", xatoda "Xato: …", aks holda ro'yxat.QueryClient— modul darajasida,retry: false.
import { useEffect, useState } from "react";
function fetchDrinks() {
return new Promise((resolve) =>
setTimeout(() => resolve(["Ko'k choy", "Kompot"]), 200),
);
}
function Drinks() {
const [drinks, setDrinks] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
let ignore = false;
fetchDrinks().then(
(data) => !ignore && setDrinks(data),
(err) => !ignore && setError(err),
);
return () => {
ignore = true;
};
}, []);
if (error) return <p>Xato: {error.message}</p>;
if (drinks === null) return <p>Yuklanmoqda…</p>;
return <p>{drinks.join(", ")}</p>;
}
export default function App() {
return <Drinks />;
}Ekranda:
Ko'k choy, KompotYechim
import {
QueryClient,
QueryClientProvider,
useQuery,
} from "@tanstack/react-query";
const queryClient = new QueryClient({
defaultOptions: { queries: { retry: false } },
});
function fetchDrinks() {
return new Promise((resolve) =>
setTimeout(() => resolve(["Ko'k choy", "Kompot"]), 200),
);
}
function Drinks() {
const { isPending, isError, error, data } = useQuery({
queryKey: ["drinks"],
queryFn: fetchDrinks,
});
if (isPending) return <p>Yuklanmoqda…</p>;
if (isError) return <p>Xato: {error.message}</p>;
return <p>{data.join(", ")}</p>;
}
export default function App() {
return (
<QueryClientProvider client={queryClient}>
<Drinks />
</QueryClientProvider>
);
}Ekranda:
Ko'k choy, KompotIkkita useState, effekt va ignore ketdi. ignore vazifasini (eskirgan javobni tashlash) endi Query bajaradi. Bonus: <Drinks /> ni ikki marta qo'ysangiz ham so'rov bitta.
3-mashq (qiyin): stol buyurtmasi va to'g'ri holatlar
«Bahor» da ofitsiant stol raqamini tanlaydi va buyurtmani ko'radi. Yozing:
Tablekomponenti:tableprop'i bo'yichauseQuery(kalitda stol raqami bo'lsin),fetchOrder(table)dan buyurtma.- 5-stolda buyurtma yo'q — server xato beradi ("5-stolda buyurtma yo'q"). Bu xato qayta urinilmasin, lekin boshqa xatolar 1 marta qayta urinilsin:
retry— funksiya. - Ekranda:
isPending— "Yuklanmoqda…", xato — "Xato: …", aks holda "4-stol: Osh, Ko'k choy". - Tugmalar «4-stol» va «5-stol».
Boshlang'ich kod — ma'lumot va soxta server:
const ORDERS = { 4: ["Osh", "Ko'k choy"], 7: ["Manti"] };
function fetchOrder(table) {
console.log("so'rov:", table);
return new Promise((resolve, reject) =>
setTimeout(() => {
if (ORDERS[table]) resolve(ORDERS[table]);
else reject(new Error(`${table}-stolda buyurtma yo'q`));
}, 200),
);
}Ishora: retry: (failureCount, error) => … — error.message ni tekshiring. «retry — qayta urinish» bo'limiga qarang.
Yechim
import { useState } from "react";
import {
QueryClient,
QueryClientProvider,
useQuery,
} from "@tanstack/react-query";
const queryClient = new QueryClient();
const ORDERS = { 4: ["Osh", "Ko'k choy"], 7: ["Manti"] };
function fetchOrder(table) {
console.log("so'rov:", table);
return new Promise((resolve, reject) =>
setTimeout(() => {
if (ORDERS[table]) resolve(ORDERS[table]);
else reject(new Error(`${table}-stolda buyurtma yo'q`));
}, 200),
);
}
function Table({ table }) {
const { isPending, isError, error, data } = useQuery({
queryKey: ["order", table],
queryFn: () => fetchOrder(table),
retry: (failureCount, err) =>
!err.message.includes("buyurtma yo'q") && failureCount < 1,
});
if (isPending) return <p>Yuklanmoqda…</p>;
if (isError) return <p>Xato: {error.message}</p>;
return (
<p>
{table}-stol: {data.join(", ")}
</p>
);
}
function Waiter() {
const [table, setTable] = useState(4);
return (
<>
<button onClick={() => setTable(4)}>4-stol</button>{" "}
<button onClick={() => setTable(5)}>5-stol</button>
<Table table={table} />
</>
);
}
export default function App() {
return (
<QueryClientProvider client={queryClient}>
<Waiter />
</QueryClientProvider>
);
}Konsolda:
so'rov: 4
so'rov: 5Ekranda:
4-stol 5-stol
Xato: 5-stolda buyurtma yo'qKonsolda so'rov: 5 bir marta — "buyurtma yo'q" xatosi qayta urinilmadi va darhol ekranga chiqdi. retry funksiyasi true qaytarsa — yana urinish, false — to'xtash. failureCount 0 dan boshlanadi, shuning uchun failureCount < 1 — "bir marta qayta". Haqiqiy loyihada matn o'rniga HTTP holatini tekshiring (error.status === 404) — matn o'zgarishi mumkin.
4-mashq: Vazifalar qadami
refactor/tanstack-query branch'ida «Vazifalar qadami» bo'limidagi o'zgarishlarni qiling: paket, main.tsx dagi Provider, server-sinxron.ts dagi sorovMijozi, royxatKaliti, royxatniYukla, useVazifalar, App.tsx va StatistikaSahifasi.tsx. Commit hali yo'q — mutatsiyalar darsida.
Yechim
Tekshiruv ro'yxati:
npm run tip—useReducervasinxronlaqoldiqlari tip xatosi beradi, hammasi tuzalguncha davom eting. Yozish qismi (useYozuv) keyingi ikki darsda to'liq bo'ladi.npm run dev— sahifa ochilganda DevTools Network panelida bitta GET. Statistika sahifasiga o'ting — yangi GET yo'q, raqamlar ro'yxatdagidek.- Internetni o'chiring (DevTools → Network → Offline) va sahifani yangilang: ro'yxat localStorage'dan ko'rinadi, aloqa satrida "oflayn". Internetni yoqing — so'rov o'zi ketadi.
- Hajm:
npm run build—index-….jsgzip taxminan 10 KB o'sadi (kanonda +9.9 KB).
10. Real ishda
- TanStack Query — React'da server ma'lumoti uchun eng ko'p ishlatiladigan kutubxonalardan biri. Ishga kirsangiz, loyihada
useQueryni katta ehtimol bilan uchratasiz. Unga o'xshash muqobillar — SWR va RTK Query (TanStack Query V, RTK Query darslarida). - API qatlami bilan juftlik. Odatda
queryFnlar alohida faylda:api/dishes.ts—fetch, xato va sxema tekshiruvi. Komponent faqatuseQueryni ko'radi.vazifalarda:api.ts+server-sinxron.ts. - Next.js da ham Query ishlatiladi. Server komponentlar ma'lumotni serverda oladi, klientdagi interaktiv qism esa Query bilan (Next.js qismida).
- Intervyu savollari: "TanStack Query nimani hal qiladi,
useEffect+fetchdan farqi?", "queryKeynima uchun massiv?", "isPendingvaisFetchingfarqi?", "deduplication nima?".
Xulosa
- Server ma'lumoti — keshlanadigan, eskiradigan, ko'p komponent ko'radigan narsa. Uni har komponentda qo'lda yuklash — takror so'rovlar va eskirgan raqamlar.
QueryClient— kesh,QueryClientProvider— uni daraxtga beradi,useQuery({ queryKey, queryFn })— o'qiydi.queryKey— massiv va ma'lumotning nomi: funksiya nimaga bog'liq bo'lsa, kalitda bo'ladi. Bir xil kalit — bitta so'rov.queryFn— Promise qaytaradi, xatoda tashlaydi,undefinedqaytarmaydi.status— ma'lumot bormi (pending/error/success),fetchStatus— so'rov ketyaptimi (fetching/paused/idle).- Server javobi keshga tushishidan oldin
queryFnda tekshiriladi.
Keyingi dars: TanStack Query II: kesh hayot sikli va kalitlar — staleTime va gcTime, avtomatik yangilanishlar, queryOptions, enabled, select va parallel so'rovlar; vazifalar da 7 qadamda 4 GET → 2 GET.
Manbalar
- TanStack Query v5: Overview, Quick Start — tanstack.com/query/v5/docs/framework/react/overview (2026-10, v5.104)
- TanStack Query v5: Queries, Query Keys, Query Functions — tanstack.com/query/v5/docs/framework/react/guides/queries
- TanStack Query v5: Query Retries, Network Mode — …/guides/query-retries, …/guides/network-mode
- TanStack Query v5:
useQueryAPI — …/reference/useQuery
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!