Mundarija (25)
- Bu darsda
- 1. Nega bu kerak?
- 2. Server state'ning uch xususiyati
- 2.1 Asinxron: avval "hali yo'q"
- 2.2 Umumiy: bir ma'lumot — ko'p komponent
- 2.3 Eskiradi: boshqa odam o'zgartiradi
- 2.4 Xulosa: server state — kesh
- 3. O'zingiz yasab ko'ring: eng kichik kesh
- 3.1 Bitta va'da — hamma uchun
- 4. Holatning besh turi
- 4.1 Xarita
- 4.2 Eng ko'p uchraydigan xato: nusxa
- 5. Kanon o'lchovi: vazifalar da nechta so'rov?
- 5.1 Ssenariy
- 5.2 Tahlil: ikki xil xato
- 5.3 Kelgusida: bitta kesh
- 6. Ko'p uchraydigan xatolar
- 7. Mashqlar
- 1-mashq (oson): qaysi tur?
- 2-mashq (o'rta): ikki komponent — bitta so'rov
- 3-mashq (qiyin): yangilik muddati
- 4-mashq: vazifalar ga nazar
- 8. Real ishda
- Xulosa
- Manbalar
Server state va client state: farqi, eskirish, kesh va qaysi holat qayerda saqlanadi
Qisqacha: Server state — serverda yashaydigan ma'lumotning brauzerdagi nusxasi (taomlar ro'yxati, buyurtmalar). U asinxron keladi, boshqa odam o'zgartirsa eskiradi, bir nechta sahifa uni birga ishlatadi. Shuning uchun u oddiy
useStateemas — kesh: kim, qachon, qaysi kalit bilan so'radi, qachon yangilash kerak. Client state — faqat shu brauzerniki (ochiq modal, input matni, tema). Ular orasida yana ikkitasi: URL state (filtr, sahifa) va forma state (yozilayotgan qiymatlar). Har biriga o'z vositasi: server — TanStack Query, URL — router, forma — React Hook Form, umumiy client — Context yoki Zustand, qolgani —useState.
Bu darsda
- Server state'ning uch xususiyatini (asinxron, eskiradi, umumiy) misolda ko'rasiz.
- Bir xil ma'lumotni ikki komponent so'raganda nima bo'lishini va kesh nima uchun kerakligini tushunasiz.
- Holatni besh turga ajratib, har biriga vosita tanlay olasiz.
vazifalarda sahifalar orasida yurganda nechta so'rov ketishini va statistika nega eskirganini o'lchov bilan ko'rasiz.
Oldin bilishingiz kerak: Effektda ma'lumot olish, URL — holat saqlash joyi, data mode — loader.
1. Nega bu kerak?
«Bahor» ilovasida ikki ekran bor: menyu va "bugungi statistika" (nechta taom sotuvda). Ikkalasi ham taomlar ro'yxatini ishlatadi. Sardor har biriga useEffect + fetch + useState yozdi — 17-qismda o'rgangandek. Hammasi ishlaydi. Keyin Jasur aka uchta savol berdi:
- "Menyudan statistikaga o'tsam, nega yana yuklanmoqda?" — ma'lumot bir soniya oldin olingan edi.
- "Oshxonada lag'mon tugadi, men belgiladim. Kassadagi telefonda u hali 'bor' turibdi. Nega?"
- "Statistika «3 ta taom» deyapti, menyuda 4 ta. Qaysi biri to'g'ri?"
Uchala savolning ildizi bitta: serverdan kelgan ro'yxatni oddiy state deb saqladik. Oddiy state — "men bu qiymatning egasiman" degani. Server ma'lumotining egasi esa — server. Brauzerda faqat uning surati turadi, va surat vaqt o'tib eskiradi.
Hayotiy o'xshatish — telefoningizdagi ob-havo vidjeti. U "+18°" ko'rsatadi, lekin bu harorat Toshkentniki, telefonniki emas. Vidjet ma'lumot qachon olinganini biladi ("10 daqiqa oldin yangilangan"), eskirsa — o'zi qayta so'raydi. Ikkita ilova bir xil ob-havoni so'rasa, telefon ikki marta yuklamaydi. Server state bilan ham shunday ishlash kerak.
2. Server state'ning uch xususiyati
2.1 Asinxron: avval "hali yo'q"
Server ma'lumoti darhol yo'q. Har komponent uch holatni ko'rsatishi kerak: yuklanmoqda, xato, tayyor. Bu effekt darsidan tanish — loader buni marshrut darajasiga ko'tardi (data mode). Lekin asinxronlik — eng oson muammo.
2.2 Umumiy: bir ma'lumot — ko'p komponent
Ikki komponent bir xil ro'yxatni so'raydi. Har biri o'z useEffect i bilan:
import { useEffect, useState } from "react";
let requests = 0;
// Soxta server: har chaqiruv — yangi so'rov
function fetchDishes() {
requests += 1;
console.log(`so'rov #${requests}`);
return new Promise((resolve) =>
setTimeout(() => resolve(["Osh", "Manti", "Lag'mon"]), 200),
);
}
function useDishes() {
const [dishes, setDishes] = useState(null);
useEffect(() => {
fetchDishes().then(setDishes);
}, []);
return dishes;
}
function Menu() {
const dishes = useDishes();
return <p>Menyu: {dishes ? dishes.join(", ") : "…"}</p>;
}
function Stats() {
const dishes = useDishes();
return <p>Sotuvda: {dishes ? dishes.length : "…"} ta</p>;
}
export default function App() {
return (
<>
<Menu />
<Stats />
</>
);
}Konsolda:
so'rov #1
so'rov #2Ekranda:
Menyu: Osh, Manti, Lag'mon
Sotuvda: 3 taBir ma'lumot — ikki so'rov. Sahifada beshta shunday komponent bo'lsa — beshta. Bundan ham yomoni: so'rovlar har xil vaqtda qaytsa, ekranning bir qismi eski, boshqa qismi yangi ma'lumotni ko'rsatadi. Bu — Jasur akaning uchinchi savoli.
2.3 Eskiradi: boshqa odam o'zgartiradi
Ma'lumot brauzerga kelgan zahoti eskira boshlaydi. Kassir lag'monni "tugadi" deb belgiladi — sizning ekraningiz buni bilmaydi:
import { useEffect, useState } from "react";
// "Server": 250 ms dan keyin boshqa qurilma lag'monni o'chiradi
let serverDishes = ["Osh", "Manti", "Lag'mon"];
setTimeout(() => {
serverDishes = ["Osh", "Manti"];
}, 250);
const fetchDishes = () =>
new Promise((resolve) =>
setTimeout(() => resolve([...serverDishes]), 100),
);
export default function App() {
const [dishes, setDishes] = useState(null);
const [loadedAt, setLoadedAt] = useState(0);
function load() {
fetchDishes().then((list) => {
setDishes(list);
setLoadedAt((n) => n + 1);
});
}
useEffect(load, []);
return (
<section>
<p>
{loadedAt}-yuklash: {dishes ? dishes.join(", ") : "…"}
</p>
<button onClick={load}>Yangilash</button>
</section>
);
}Ekranda:
2-yuklash: Osh, Manti
YangilashBirinchi yuklashda — uch taom. 250 ms da serverda lag'mon o'chdi, lekin ekran buni bilmadi: u eskirgan surat ni ko'rsatib turdi (harakat qatoridagi ekran qadami 500 ms dan keyin buni tekshirdi). Faqat «Yangilash» dan keyin — ikki taom. Haqiqiy ilovada "yangilash" tugmasini hech kim bosmaydi. Kimdir qachon qayta so'rash kerakligini hal qilishi kerak: sahifaga qaytganda? oyna fokus olganda? har 30 soniyada? internet qaytganda?
2.4 Xulosa: server state — kesh
| Client state | Server state | |
|---|---|---|
| Egasi | brauzer (shu komponent) | server |
| Paydo bo'lishi | darhol | asinxron (so'rov) |
| Kim o'zgartiradi | faqat shu foydalanuvchi | hamma (boshqa qurilma, admin) |
| Eskiradimi | yo'q | ha, kelgan zahoti |
| Kim ishlatadi | odatda bitta komponent | ko'p sahifa va komponent |
Shuning uchun server state'ni boshqarish — keshni boshqarish:
- kalit — "qaysi ma'lumot" (
["taomlar"],["taom", 2]); - takrorni birlashtirish (deduplication) — bir kalitni bir vaqtda o'nta komponent so'rasa, bitta so'rov;
- yangilik muddati — "bu surat qancha vaqt yangi hisoblanadi" (TanStack Query'da
staleTime; muddati o'tgan ma'lumot — eskirgan, inglizcha stale); - qayta so'rash qoidalari — qachon fonda yangilash;
- o'zgartirgandan keyin — qaysi keshni eskirgan deb belgilash.
Buni har loyihada qo'lda yozish mumkin. Lekin bu — bir necha yuz qator nozik kod (poyga holatlari, bekor qilish, xatoda qayta urinish). Shuning uchun maxsus kutubxonalar bor: TanStack Query (kursda), SWR, RTK Query.
3. O'zingiz yasab ko'ring: eng kichik kesh
3.1 Bitta va'da — hamma uchun
Kesh g'oyasini qo'lda, 20 qatorda ko'ramiz — TanStack Query'ning ichida nima bo'lishini his qilish uchun. Asosiy hiyla: kalit bo'yicha Promise ni saqlash. Ikkinchi komponent so'raganda yangi so'rov emas, o'sha va'da qaytadi:
import { useEffect, useState } from "react";
let requests = 0;
function fetchDishes() {
requests += 1;
console.log(`so'rov #${requests}`);
return new Promise((resolve) =>
setTimeout(() => resolve(["Osh", "Manti", "Lag'mon"]), 200),
);
}
// kalit → { promise, time }
const cache = new Map();
function getCached(key, fetcher) {
if (!cache.has(key)) {
cache.set(key, { promise: fetcher(), time: Date.now() });
}
return cache.get(key).promise;
}
function useCached(key, fetcher) {
const [data, setData] = useState(null);
useEffect(() => {
let active = true;
getCached(key, fetcher).then((d) => active && setData(d));
return () => {
active = false;
};
}, [key, fetcher]);
return data;
}
function Menu() {
const dishes = useCached("taomlar", fetchDishes);
return <p>Menyu: {dishes ? dishes.join(", ") : "…"}</p>;
}
function Stats() {
const dishes = useCached("taomlar", fetchDishes);
return <p>Sotuvda: {dishes ? dishes.length : "…"} ta</p>;
}
export default function App() {
return (
<>
<Menu />
<Stats />
</>
);
}Konsolda:
so'rov #1Ekranda:
Menyu: Osh, Manti, Lag'mon
Sotuvda: 3 taBitta so'rov, ikkala komponent bir xil ma'lumot. active bayrog'i — poyga holatidan himoya: komponent o'chib ketgan bo'lsa, setData chaqirilmaydi.
Bu keshda nima yetishmaydi? Yangilik muddati yo'q (time saqlanadi, lekin ishlatilmaydi) — ma'lumot abadiy "yangi". Xato bo'lsa, xato ham abadiy keshda qoladi. O'zgartirgandan keyin keshni tozalash yo'q. Bir komponent keshni yangilasa, boshqasi bilmaydi (obuna yo'q). Har bandi — yana o'nlab qator. TanStack Query aynan shularni beradi — TanStack Query I dan boshlab.
Tekshirib ko'ring:
getCacheddapromiseo'rniga natijani saqlasak (cache.set(key, data)— javob kelgandan keyin), ikki komponent bir vaqtda so'raganda nechta so'rov ketadi?
Javob
Ikkita. Ikkinchi komponent so'raganda birinchi so'rov hali qaytmagan — keshda hech narsa yo'q, u ham yangi so'rov yuboradi. Promise'ni darhol saqlash "so'rov ketgan, kuting" degan holatni ham keshga yozadi. Bu — takrorni birlashtirish (deduplication) ning asosiy hiylasi.
4. Holatning besh turi
4.1 Xarita
Server va client — ikki asosiy tur. Lekin real ilovada ular orasida yana ikkitasi bor, va har biriga o'z vositasi:
| Tur | Misol | Vosita (kursda) |
|---|---|---|
| Server state | taomlar, buyurtmalar, vazifalar | TanStack Query (TanStack Query I) |
| URL state | filtr, saralash, sahifa, ochiq tab | router: useSearchParams (URL — holat saqlash joyi) |
| Forma state | yozilayotgan qiymatlar, xatolar, "o'zgardimi" | React Hook Form (React Hook Form I) |
| Umumiy client state | e'lon (toast), sozlamalar, savat | Context yoki Zustand (Zustand I) |
| Mahalliy UI state | ochiq menyu, hover, input matni | useState, useReducer |
Qaysi turga tegishli ekanini savollar bilan aniqlang:
flowchart TD
A["Yangi holat"] --> B{"Asl nusxasi<br/>serverdami?"}
B -- ha --> S["Server state<br/>(kesh)"]
B -- yo'q --> C{"Havola bilan<br/>ketishi kerakmi?"}
C -- ha --> U["URL state"]
C -- yo'q --> D{"Forma maydonimi?"}
D -- ha --> F["Forma state"]
D -- yo'q --> E{"Bir nechta joy<br/>ishlatadimi?"}
E -- ha --> G["Umumiy client state"]
E -- yo'q --> L["useState"]Tartib muhim: savollar yuqoridan pastga. "Savat" — serverdami? Agar buyurtma faqat "Rasmiylashtirish" da yuborilsa — yo'q, u umumiy client state (va ehtimol localStorage da). Agar savat serverda saqlansa (boshqa qurilmada ham ko'rinsin) — server state.
4.2 Eng ko'p uchraydigan xato: nusxa
Server ma'lumotini olib, nusxasini useState ga yoki global store'ga yozish:
// ❌ server ma'lumotining nusxasi — endi ikki "haqiqat"
const { data } = useTaomlar(); // kesh
const [taomlar, setTaomlar] = useState(data); // nusxauseState(data) faqat birinchi qiymatni oladi (State II). Kesh yangilansa, nusxa eskicha qoladi. Endi ikkita "haqiqat" bor va ular ajraladi. Qoida: server ma'lumotini o'qing, nusxalamang. Uni o'zgartirmoqchi bo'lsangiz — serverga yozing va keshni yangilang (mutatsiya — TanStack Query III). Faqat tahrir formasining boshlang'ich qiymati sifatida nusxa olish to'g'ri — u allaqachon forma state.
Redux davridagi loyihalarda ko'p uchraydi: serverdan kelgan hamma narsa global store'da, har sahifada dispatch(setTaomlar(...)). Bu — server state'ni client state deb boshqarish. Zamonaviy yondashuv: store'da faqat haqiqiy client state, server ma'lumoti — keshda.
5. Kanon o'lchovi: vazifalar da nechta so'rov?
5.1 Ssenariy
Hozirgi vazifalar (holat 10) server ma'lumotini uch joyda ishlatadi: ro'yxat sahifasi (17–18-qismdan qolgan qo'lda kod — useEffect, pult, "kutilmoqda" hisobi), vazifa sahifasi (loader, 05-dars) va statistika (brauzerdagi nusxadan). Kanon Chrome 155 da yetti qadamni bosib, har qadamda serverga ketgan so'rovlarni sanadi (olchov/sorovlar.mjs, soxta server). Oltinchi qadamda serverga boshqa qurilmadan bitta vazifa qo'shildi.
natijalar/11-sorovlar-oldin.txt (aynan):
1. ro'yxat ochildi so'rovlar: GET | 2 ta vazifa qoldi, 1 ta bajarildi
2. → Statistika so'rovlar: — | 3/2/1 (33%)
3. → Ro'yxat so'rovlar: GET | 2 ta vazifa qoldi, 1 ta bajarildi
4. → «Batafsil» (vazifa 1) so'rovlar: GET |
5. Orqaga → Ro'yxat so'rovlar: GET | 2 ta vazifa qoldi, 1 ta bajarildi
6. serverda +1 vazifa (boshqa qurilma); → Statistika so'rovlar: — | 3/2/1 (33%)
7. Statistika — sahifa yangilandi (F5) so'rovlar: — | 3/2/1 (33%)Statistika ustuni: jami / faol / bajarilgan (foiz).
5.2 Tahlil: ikki xil xato
Ortiqcha so'rovlar. Yetti qadamda to'rtta GET. Uchinchi va beshinchi qadamda ro'yxatga qaytish — har safar yangi so'rov, garchi ro'yxat bir necha soniya oldin olingan bo'lsa ham. To'rtinchi qadamda vazifa sahifasining loader'i o'sha ro'yxatni yana so'raydi: ikki sahifa bitta ma'lumotni bo'lishmaydi. Bu — «Umumiy» bo'limidagi muammo, haqiqiy ilovada.
Eskirgan ma'lumot. 6-qadam: serverda endi 4 ta vazifa, statistika esa "3". 7-qadam: sahifani yangiladik — baribir "3"! Statistika serverga umuman so'ramaydi, u brauzerdagi nusxani o'qiydi. Nusxani esa faqat ro'yxat sahifasi yangilaydi. Foydalanuvchi statistikada qancha o'tirsa ham, F5 bossa ham — eskirgan raqam. Bu — «Eskiradi» bo'limidagi muammo.
Ajablanarlisi: bir ilovada ikkala muammo birga — bir joyda haddan tashqari ko'p so'rov, boshqa joyda — hech qanday. Sabab: har sahifa server ma'lumotini o'zicha, o'z qoidasi bilan boshqaradi. Yagona "kesh egasi" yo'q.
5.3 Kelgusida: bitta kesh
TanStack Query darslarida (13–15-darslar) vazifalar ning o'qish va yozish kodi bitta keshga — bitta queryKey ga ko'chadi. Xuddi shu ssenariy keyin qayta o'lchandi. Natijani oldindan ko'rsatamiz — bugungi tahlil nimaga olib kelishini ko'rish uchun:
- Hozir (qo'lda kod)statistika eskiradi4 ta
- Query, staleTime 30 s (kanon)2 ta
- Query, staleTime 07 ta
Manba: O'lchandi: olchov/sorovlar.mjs, Chrome 155, natijalar/11-sorovlar-oldin.txt, 14-sorovlar-keyin.txt, 14-sorovlar-stale0.txt, 2026-10-13
Ikkita GET — va 7-qadamda statistika "4/3/1 (25%)": to'g'ri raqam. Uchinchi ustun — "yangilik muddati 0" (har safar qayta so'rash): 7 GET, lekin 6-qadamdayoq to'g'ri raqam. Ikki chekka orasida tanlov bor: kamroq so'rov yoki tezroq yangilik. Kanon 30 soniyani tanladi — TanStack Query II darsida nega ekanini ko'ramiz.
vazifalar ning boshqa holatlari ham xaritaga tushadi:
| Holat | Tur | Hozir | Keyin |
|---|---|---|---|
| vazifalar ro'yxati | server | qo'lda kod + nusxa | TanStack Query (13-dars) |
| filtr, saralash | URL | useSearchParams |
o'zgarmaydi (9-dars) |
| tahrir formasi | forma | useState |
React Hook Form (29-dars) |
| e'lon, sozlamalar | umumiy client | Context | Zustand (21-dars) |
| ochiq tahrir qatori | mahalliy UI | useReducer |
useState (13-dars) |
Bu darsda kod o'zgarmaydi — bu xarita keyingi o'n darsning rejasi.
Tekshirib ko'ring: 7-qadamda (statistika, F5) eski kod nega serverga so'ramadi, garchi sahifa butunlay qayta yuklangan bo'lsa ham?
Javob
Statistika sahifasi ma'lumotni serverdan emas, localStorage dagi nusxadan o'qiydi. F5 sahifani qayta yuklaydi, lekin localStorage ni tozalamaydi — o'sha eski nusxa yana o'qiladi. Nusxani faqat ro'yxat sahifasi (serverdan olganda) yangilaydi. "Sahifa yangilansa, ma'lumot yangi bo'ladi" degan taxmin — server ma'lumotining nusxasi bilan ishlaganda yolg'on.
6. Ko'p uchraydigan xatolar
| Belgi | Sabab | Davosi |
|---|---|---|
| bir ma'lumot — bir necha bir xil so'rov | har komponent o'zi fetch qiladi |
kalit bo'yicha kesh (TanStack Query) |
| sahifaga har qaytganda "Yuklanmoqda…" | kesh yo'q | yangilik muddati (staleTime) |
| ekranning ikki qismi har xil raqam | bitta ma'lumotning ikki nusxasi | bitta manba, nusxa yo'q |
server ma'lumoti useState(data) da, yangilanmaydi |
useState faqat boshlang'ich qiymatni oladi |
to'g'ridan keshdan o'qing |
| boshqa qurilmadagi o'zgarish ko'rinmaydi | qayta so'rash qoidasi yo'q | fokusda, qayta ulanishda, intervalda yangilash |
| filtr global store'da, havolada yo'q | URL state client state deb saqlangan | useSearchParams |
7. Mashqlar
Mashqlar kurs/mashqlar/19/11-server-client/ da.
1-mashq (oson): qaysi tur?
Har holat uchun turni yozing (server, URL, forma, client, UI):
- Buyurtmalar ro'yxati (oshxona ekrani) →
- Ro'yxatda tanlangan "faqat tayyorlanayotganlar" filtri →
- "Yangi taom" formasidagi narx maydoni →
- Butun ilova bo'ylab qorong'i/yorug' tema →
- Taom kartasida "batafsil" ochilgan-yopilgani →
Yechim
Buyurtmalar — serverda yashaydi, boshqa ekranlar (kassa, oshxona) o'zgartiradi: server state. Filtr — havola bilan ketsa foydali: URL. Narx maydoni — hali yuborilmagan qiymat: forma. Tema — bir nechta komponent ishlatadi, server bilmaydi: umumiy client (odatda localStorage bilan). "Batafsil" — faqat shu karta: mahalliy UI, useState. «Xarita» bo'limidagi savollar ketma-ketligi aynan shu javoblarga olib boradi.
2-mashq (o'rta): ikki komponent — bitta so'rov
Quyidagi ilovada Header va Cart foydalanuvchi ismini alohida so'raydi — konsolda ikkita so'rov. «Bitta va'da — hamma uchun» bo'limidagi g'oya bilan fetchUser ni o'rang: bir vaqtda kelgan chaqiruvlar bitta Promise'ni olsin.
import { useEffect, useState } from "react";
let requests = 0;
function fetchUser() {
requests += 1;
console.log(`so'rov #${requests}`);
return new Promise((resolve) =>
setTimeout(() => resolve({ name: "Malika" }), 200),
);
}
function useUser() {
const [user, setUser] = useState(null);
useEffect(() => {
fetchUser().then(setUser);
}, []);
return user;
}
function Header() {
const user = useUser();
return <p>Salom, {user?.name ?? "…"}</p>;
}
function Cart() {
const user = useUser();
return <p>{user?.name ?? "…"} savati: 2 ta osh</p>;
}
export default function App() {
return (
<>
<Header />
<Cart />
</>
);
}Konsolda:
so'rov #1
so'rov #2Yechim
import { useEffect, useState } from "react";
let requests = 0;
function fetchUser() {
requests += 1;
console.log(`so'rov #${requests}`);
return new Promise((resolve) =>
setTimeout(() => resolve({ name: "Malika" }), 200),
);
}
// Bitta umumiy va'da
let pending = null;
function fetchUserOnce() {
if (pending === null) {
pending = fetchUser();
}
return pending;
}
function useUser() {
const [user, setUser] = useState(null);
useEffect(() => {
fetchUserOnce().then(setUser);
}, []);
return user;
}
function Header() {
const user = useUser();
return <p>Salom, {user?.name ?? "…"}</p>;
}
function Cart() {
const user = useUser();
return <p>{user?.name ?? "…"} savati: 2 ta osh</p>;
}
export default function App() {
return (
<>
<Header />
<Cart />
</>
);
}Konsolda:
so'rov #1Ekranda:
Salom, Malika
Malika savati: 2 ta oshBitta so'rov. Kamchiligi: pending hech qachon tozalanmaydi — foydalanuvchi ismini o'zgartirsa ham, ilova eskisini ko'rsataveradi. Haqiqiy kesh "yangilik muddati" va "eskirgan deb belgilash" (invalidate) ni ham biladi — 3-mashqda.
3-mashq (qiyin): yangilik muddati
getCached(key, fetcher, staleMs) funksiyasini yozing (Node'da, React'siz). Qoidalar:
- Keshda yo'q — so'rov, Promise va vaqt saqlanadi.
- Bor va
staleMsdan yangi — o'sha Promise. - Bor, lekin eskirgan — yangi so'rov.
Vaqtni o'zingiz boshqaring: now — o'zgaruvchi (soxta soat), haqiqiy vaqtga bog'liq bo'lmasin. Ishora: Map va «Bitta va'da» bo'limidagi kod.
Yechim
let now = 0; // soxta soat, ms
let requests = 0;
const fetchDishes = () => {
requests += 1;
return Promise.resolve(["Osh", "Manti"]);
};
const cache = new Map();
function getCached(key, fetcher, staleMs) {
const entry = cache.get(key);
if (entry !== undefined && now - entry.time < staleMs) {
return entry.promise; // hali yangi
}
const fresh = { promise: fetcher(), time: now };
cache.set(key, fresh);
return fresh.promise;
}
getCached("taomlar", fetchDishes, 30000); // 0 ms — yangi so'rov
now = 10000;
getCached("taomlar", fetchDishes, 30000); // 10 s — keshdan
now = 45000;
getCached("taomlar", fetchDishes, 30000); // 45 s — eskirgan
console.log(requests); // 2Uch chaqiruv — ikki so'rov. 10 soniyada ma'lumot hali "yangi" (30 dan kam), 45 soniyada — eskirgan. Bu — TanStack Query'ning staleTime sozlamasining sodda modeli; kanon vazifalar da aynan 30 soniyani tanladi. Haqiqiy Query undan ham ko'proq qiladi: eskirgan ma'lumotni darhol ko'rsatib, fonda yangilaydi — foydalanuvchi "Yuklanmoqda…" ni ko'rmaydi.
4-mashq: vazifalar ga nazar
Bu darsda vazifalar o'zgarmaydi. npm run dev bilan ilovani oching, DevTools → Network, filtr "vazifalar". Kanon ssenariysining 1–5 qadamlarini qo'lda bajarib, GET'larni sanang. Keyin src/ da server ma'lumoti o'qiladigan joylarni toping: api.royxat chaqiruvlari va yukla() (localStorage nusxasi).
Yechim
Network'da to'rtta GET (1, 3, 4, 5-qadamlar) — natijalar/11-sorovlar-oldin.txt bilan bir xil. api.royxat — ro'yxat sahifasining sinxron kodi (server-sinxron.ts) va vazifa loader'i (vazifa-marshruti.ts). yukla() — statistika, vazifa loader'ining zaxirasi va ro'yxatning birinchi chizilishi. Uch joy, uch qoida, yagona ega yo'q — 13-darsdagi refaktor aynan shularni bitta queryKey ga yig'adi.
8. Real ishda
- "Server state" atamasi — TanStack Query (avvalgi nomi React Query) muallifi Tanner Linsley va jamoasining 2020-yildagi chiqishlaridan keng tarqaldi. Shundan beri React jamoalarida standart bo'linish: "server keshi alohida, client state alohida".
- Redux'dan ko'chish — eski loyihalarda serverdan kelgan hamma narsa Redux store'da. Zamonaviy refaktor: server qismini RTK Query yoki TanStack Query'ga, store'da faqat client state (Redux Toolkit darsida).
- Next.js — server komponentlar server state'ni yana bir qadam olib boradi: ma'lumot serverda o'qiladi va brauzerga HTML bo'lib keladi (Next.js qismi).
- Intervyu savollari: "server state va client state farqi?", "nega serverdan kelgan ma'lumotni Redux'ga qo'ymaslik kerak?", "stale-while-revalidate nima?".
Xulosa
- Server state — serverdagi ma'lumotning brauzerdagi surati: asinxron keladi, eskiradi, ko'p joyda ishlatiladi. U — kesh, oddiy state emas.
- Kesh vazifalari: kalit, takrorni birlashtirish, yangilik muddati, qayta so'rash, o'zgartirishdan keyin eskirgan deb belgilash.
- Besh tur: server (TanStack Query), URL (router), forma (React Hook Form), umumiy client (Context/Zustand), mahalliy UI (
useState). - Server ma'lumotini nusxalamang (
useState(data)) — ikki "haqiqat" ajraladi. vazifalaro'lchovi: 7 qadamda 4 GET (ortiqcha), statistika esa F5 dan keyin ham eskirgan — yagona kesh egasi yo'q.
Keyingi dars: API qatlami va type-safe kontrakt — barcha so'rovlar bitta qatlamda, server javobi esa Zod sxemasi bilan tekshiriladi: "kutilgan shaklda emas" xatosi ekranni buzmaydi.
Manbalar
- TanStack Query: Overview ("server state" muammolari), Important Defaults — tanstack.com/query/latest/docs (2026-10 holatiga)
- React: "You Might Not Need an Effect", "Choosing the State Structure" — react.dev/learn
- web.dev: stale-while-revalidate — web.dev/articles/stale-while-revalidate
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!