IlmHamroh
JavaScript Full-stack/19-qism. React: routing, server state, formalar11/36-dars17 daqiqa
Mundarija (25)

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 useState emas — 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.
  • vazifalar da 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:

  1. "Menyudan statistikaga o'tsam, nega yana yuklanmoqda?" — ma'lumot bir soniya oldin olingan edi.
  2. "Oshxonada lag'mon tugadi, men belgiladim. Kassadagi telefonda u hali 'bor' turibdi. Nega?"
  3. "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:

jsx
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:

text
so'rov #1
so'rov #2

Ekranda:

text
Menyu: Osh, Manti, Lag'mon
Sotuvda: 3 ta

Bir 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:

jsx
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:

text
2-yuklash: Osh, Manti
Yangilash

Birinchi 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:

jsx
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:

text
so'rov #1

Ekranda:

text
Menyu: Osh, Manti, Lag'mon
Sotuvda: 3 ta

Bitta 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: getCached da promise o'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:

jsx
// ❌ server ma'lumotining nusxasi — endi ikki "haqiqat"
const { data } = useTaomlar();          // kesh
const [taomlar, setTaomlar] = useState(data); // nusxa

useState(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):

text
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:

vazifalar: 7 qadamda serverga GET so'rovlari
  • 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):

  1. Buyurtmalar ro'yxati (oshxona ekrani) →
  2. Ro'yxatda tanlangan "faqat tayyorlanayotganlar" filtri →
  3. "Yangi taom" formasidagi narx maydoni →
  4. Butun ilova bo'ylab qorong'i/yorug' tema →
  5. 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.

jsx
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:

text
so'rov #1
so'rov #2
Yechim
jsx
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:

text
so'rov #1

Ekranda:

text
Salom, Malika
Malika savati: 2 ta osh

Bitta 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:

  1. Keshda yo'q — so'rov, Promise va vaqt saqlanadi.
  2. Bor va staleMs dan yangi — o'sha Promise.
  3. 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
js
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); // 2

Uch 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.
  • vazifalar o'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
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Server state va client state: farqi, eskirish, kesh va qaysi holat qayerda saqlanadi — IlmHamroh