State boshqarish muammolari β€” qachon global state kerak

~15 daq Β· React Β· State Boshqarish

Muammodan boshlaylik

Internet do'kon. Savatdagi mahsulotlar soni uch joyda kerak:

  • Header dagi savat belgisida: πŸ›’ 3
  • Mahsulot kartochkasi dagi "Savatga" tugmasida
  • Savat sahifasida

Komponentlar daraxti:

App
β”œβ”€β”€ Header
β”‚   └── SavatBelgisi        ← savat kerak
β”œβ”€β”€ Routes
β”‚   β”œβ”€β”€ Katalog
β”‚   β”‚   └── MahsulotRoyxati
β”‚   β”‚       └── MahsulotKartochka   ← savat kerak
β”‚   └── SavatSahifasi       ← savat kerak
└── Footer

useState ni App da yozib, props orqali pastga uzatish β€” prop drilling (7-dars): Katalog va MahsulotRoyxati savatni o'zlari ishlatmaydi, faqat uzatadi. Context (18-dars) bu muammoni hal qiladi, lekin savat o'zgarganda butun ilova qayta render bo'ladi.

Endi savol: qaysi state ni global qilish kerak, qaysini β€” yo'q? Va qaysi vosita bilan?


State ning to'rt turi

Ko'p "state boshqarish" muammolari state ni noto'g'ri turga qo'yishdan kelib chiqadi:

Tur Misol To'g'ri vosita
Lokal UI state Modal ochiqmi, input qiymati, tanlangan tab useState, useReducer β€” komponent ichida
Server state Mahsulotlar, profil, buyurtmalar TanStack Query (51–55-darslar)
URL state Filtrlar, sahifa raqami, qidiruv so'zi, tanlangan element URL β€” useParams, useSearchParams (43–44-darslar)
Global client state Savat, qorong'i rejim, tizimga kirgan foydalanuvchi tokeni, til Context, Zustand, Redux

Haqiqiy global client state β€” ko'pchilik o'ylagandan ancha kam.


Avval tekshiring: bu haqiqatan global state mi?

1. Bu server ma'lumotimi?

// ❌ Server ma'lumotini global store ga yuklash
const useStore = create((set) => ({
  mahsulotlar: [],
  yuklanmoqda: false,
  mahsulotlarniYukla: async () => { ... },
}));

// βœ… TanStack Query β€” kesh, yangilash, deduplikatsiya bepul
const { data: mahsulotlar } = useMahsulotlar();

Bir necha yil oldin Redux store larining 80% i server ma'lumotlari edi β€” loading, error, data uchun qo'lda yozilgan reducerlar bilan. TanStack Query paydo bo'lgandan keyin global state ga ehtiyoj keskin kamaydi.

2. Bu URL da bo'lishi kerakmi?

// ❌ Filtr global store da β€” sahifa yangilansa yo'qoladi, havolani ulashib bo'lmaydi
const kategoriya = useStore((s) => s.kategoriya);

// βœ… URL da β€” /katalog?kategoriya=kitob&sahifa=2
const [params] = useSearchParams();
const kategoriya = params.get('kategoriya');

Agar foydalanuvchi sahifani yangilaganda yoki havolani do'stiga yuborganda bu holat saqlanishi kerak bo'lsa β€” u URL da bo'lishi kerak.

3. State ni yaqinroq joyga ko'chirish mumkinmi?

// ❌ Modal holati global
const modalOchiq = useStore((s) => s.modalOchiq);

// βœ… Modal ni ochadigan komponentda
const [ochiq, setOchiq] = useState(false);

State ni uni ishlatadigan komponentlarning eng yaqin umumiy ota-onasida saqlang. Faqat ikki-uch daraja pastga uzatilsa β€” props yetarli, bu "drilling" emas.

4. Composition yordam beradimi?

// ❌ Layout savatni o'zi ishlatmaydi, faqat uzatadi
<Layout savat={savat}>...</Layout>

// βœ… children orqali β€” Layout savat haqida bilmaydi
<Layout header={<SavatBelgisi savat={savat} />}>
  ...
</Layout>

30-darsdagi composition prop drilling ning ko'p holatlarini hal qiladi.

[!TIP] Qaror ketma-ketligi: server ma'lumotimi β†’ TanStack Query. URL da saqlanishi kerakmi β†’ URL. Bitta komponentga kerakmi β†’ useState. Bir nechta yaqin komponentga β†’ ota-onaga ko'tarish yoki composition. Faqat shundan keyin β€” global state.


Context β€” qachon yetarli

Context (18-dars) β€” React ning o'zidagi global vosita. U kamdan-kam o'zgaradigan qiymatlar uchun juda yaxshi:

<ThemeContext.Provider value={mavzu}>        // qorong'i/yorug' rejim
<AuthContext.Provider value={foydalanuvchi}> // kim tizimga kirgan
<LocaleContext.Provider value={til}>         // til

Context ning cheklovi

const SavatContext = createContext();

function SavatProvider({ children }) {
  const [savat, setSavat] = useState([]);
  const [promokod, setPromokod] = useState('');
  return (
    <SavatContext.Provider value={{ savat, setSavat, promokod, setPromokod }}>
      {children}
    </SavatContext.Provider>
  );
}

value dagi istalgan narsa o'zgarsa β€” Context ni ishlatadigan barcha komponentlar qayta render bo'ladi. Promokod yozilayotganda har bir harf SavatBelgisi ni ham, har bir MahsulotKartochka ni ham qayta chizadi β€” garchi ular faqat savat.length ni ishlatsa ham.

Context da "faqat menga kerakli qismni kuzat" (selektor) imkoniyati yo'q. Buni kontekstlarni bo'lish, useMemo va memo bilan yumshatish mumkin, lekin kod tezda murakkablashadi.


Global state kutubxonalari

Context Zustand Redux Toolkit
O'rnatish Kerak emas ~1 KB ~15 KB
Boilerplate Kam Juda kam O'rtacha
Selektorlar (qisman render) ❌ βœ… βœ…
Provider kerakmi βœ… ❌ βœ…
DevTools ❌ βœ… (Redux DevTools orqali) βœ… Eng kuchli
Komponentdan tashqarida ishlatish ❌ βœ… βœ…
Qachon Kamdan-kam o'zgaradigan: mavzu, til, auth Ko'p loyihalar uchun standart tanlov Katta jamoalar, qat'iy arxitektura, murakkab mantiq

Keyingi darslarda β€” Zustand (57–58) va Redux Toolkit (59–61).


Savat β€” to'g'ri tahlil

Darsning boshidagi savatni tahlil qilamiz:

  • Server ma'lumotimi? Agar foydalanuvchi tizimga kirgan bo'lsa va savat serverda saqlansa β€” ha, TanStack Query. Mehmon savati faqat brauzerda bo'lsa β€” yo'q
  • URL dami? Yo'q β€” sahifalar orasida saqlanishi kerak, lekin havolada emas
  • Bitta komponentmi? Yo'q β€” uch xil joyda, daraxtning turli shoxlarida
  • Tez-tez o'zgaradimi? Ha β€” har "Savatga" bosilganda

Natija: mehmon savati β€” global client state uchun yaxshi nomzod. Zustand bilan β€” keyingi darsda.


Nima uchun shunday?

Nima uchun ko'p dasturchilar hamma narsani global store ga qo'yadi β€” va nima uchun bu muammo?

Chunki global state birinchi qarashda qulay: istalgan komponentdan istalgan ma'lumotga yetish mumkin, props uzatish shart emas. Lekin bu qulaylik qimmatga tushadi. Global state β€” bu global o'zgaruvchi, va global o'zgaruvchilarning muammolari dasturlashda 50 yildan beri ma'lum: kim o'zgartirdi β€” noma'lum, nima unga bog'liq β€” noma'lum, komponentni boshqa joyda qayta ishlatib bo'lmaydi, testlash qiyin. Lokal state esa komponent bilan birga tug'iladi va o'ladi β€” u haqida o'ylash oson. Shuning uchun yaxshi qoida: state ni iloji boricha lokal saqlang va faqat haqiqiy zarurat bo'lganda yuqoriga ko'taring.


Xulosa

Eslab qoling:

  • State turlari: lokal UI, server, URL, global client
  • Server ma'lumoti β€” TanStack Query; filtr va sahifa β€” URL; modal holati β€” useState
  • Avval: state ni yaqin ota-onaga ko'tarish va composition; global β€” oxirgi qadam
  • Context β€” kamdan-kam o'zgaradigan qiymatlar uchun (mavzu, til, auth); value o'zgarsa barcha iste'molchilar render bo'ladi
  • Tez-tez o'zgaradigan global state β€” Zustand yoki Redux Toolkit (selektorlar bilan)
  • Haqiqiy global client state β€” odatda kam: savat, sozlamalar, auth token

Keyingi dars

57-dars: Zustand β€” o'rnatish, store yaratish, ishlatish