useReducer + useContext — o'z state manager ini yozish
Ikkalasini birlashtirish
Oldingi darslarda ikki narsa o'rgandik:
useContext— ma'lumotni istalgan komponentga yetkazadiuseReducer— murakkab state o'zgarishlarini tartibli boshqaradi
Ikkalasini birlashtirish — Redux ga o'xshash oddiy global state manager hosil qiladi. Qo'shimcha kutubxona kerak emas.
Tasavvur qiling: savat state bor. Uni istalgan komponentdan o'zgartirish kerak. useReducer — o'zgartirish mantiqini boshqaradi. useContext — state va dispatch ni istalgan komponentga yetkazadi.
useReducer → state va dispatch yaratadi
useContext → ularni istalgan komponentga yetkazadi
Natija:
istalgan komponent
dispatch({ type: 'QOSHISH' }) → global state o'zgardi
state.mahsulotlar → global state dan o'qish
To'liq misol — savat
// SavatContext.jsx
import { createContext, useContext, useReducer } from 'react';
// Reducer — barcha mantiq shu yerda
function savatReducer(state, action) {
switch (action.type) {
case 'QOSHISH': {
const bor = state.find(m => m.id === action.payload.id);
if (bor) {
// allaqachon bor — sonini oshir
return state.map(m =>
m.id === action.payload.id ? { ...m, son: m.son + 1 } : m
);
}
// yangi mahsulot — qo'sh
return [...state, { ...action.payload, son: 1 }];
}
case 'KAMAYTIR':
return state
.map(m => m.id === action.payload ? { ...m, son: m.son - 1 } : m)
.filter(m => m.son > 0); // son 0 ga tushsa — o'chir
case 'OCHIRISH':
return state.filter(m => m.id !== action.payload);
case 'TOZALA':
return [];
default:
return state;
}
}
// Context
const SavatContext = createContext();
// Provider — App ni o'raydi
export function SavatProvider({ children }) {
const [savat, dispatch] = useReducer(savatReducer, []);
// Hisoblangan qiymatlar — har render da yangilanadi
const jami = savat.reduce((sum, m) => sum + m.narx * m.son, 0);
const soni = savat.reduce((sum, m) => sum + m.son, 0);
return (
<SavatContext.Provider value={{ savat, dispatch, jami, soni }}>
{children}
</SavatContext.Provider>
);
}
// Custom hook
export function useSavat() {
const context = useContext(SavatContext);
if (!context) throw new Error('useSavat SavatProvider ichida ishlatilishi kerak');
return context;
}
Endi istalgan komponentda useSavat() chaqiriladi:
// Navbar.jsx
function Navbar() {
const { soni } = useSavat();
return <nav>🛒 {soni}</nav>;
}
// MahsulotKarta.jsx
function MahsulotKarta({ mahsulot }) {
const { dispatch } = useSavat();
return (
<div>
<h3>{mahsulot.nomi}</h3>
<button onClick={() => dispatch({ type: 'QOSHISH', payload: mahsulot })}>
Savatga qo'shish
</button>
</div>
);
}
// SavatSahifa.jsx
function SavatSahifa() {
const { savat, dispatch, jami } = useSavat();
if (savat.length === 0) return <p>Savat bo'sh</p>;
return (
<div>
{savat.map(m => (
<div key={m.id}>
<span>{m.nomi}</span>
<button onClick={() => dispatch({ type: 'KAMAYTIR', payload: m.id })}>−</button>
<span>{m.son}</span>
<button onClick={() => dispatch({ type: 'QOSHISH', payload: m })}>+</button>
<button onClick={() => dispatch({ type: 'OCHIRISH', payload: m.id })}>✕</button>
</div>
))}
<strong>Jami: {jami.toLocaleString()} so'm</strong>
<button onClick={() => dispatch({ type: 'TOZALA' })}>Savatni tozala</button>
</div>
);
}
Arxitektura
SavatProvider
├── savatReducer ← barcha mantiq shu yerda
├── SavatContext ← state va dispatch tarqatiladi
│
├── Navbar → useSavat() → soni
├── MahsulotKarta → useSavat() → dispatch(QOSHISH)
└── SavatSahifa → useSavat() → savat, dispatch, jami
Har bir komponent faqat kerakli narsani oladi. Mantiq bir joyda — savatReducer. Yangi amal kerak bo'lsa — faqat reducerga qo'shiladi, komponentlarga tegmaydi.
Bu pattern qachon yetarli, qachon emas?
useReducer + useContext:
✅ O'rta murakkablikdagi global state
✅ Qo'shimcha kutubxona kerak emas
✅ Redux ni o'rganishdan oldin tushunish uchun yaxshi
❌ Tez-tez o'zgaradigan katta state da sekin
(har o'zgarishda barcha consumer qayta chiziladi)
❌ DevTools yo'q
Zustand:
✅ Oddiyroq sintaksis
✅ Tez-tez o'zgaradigan state uchun optimallashtirilgan
✅ Minimal kod
Savat, foydalanuvchi, tema — useReducer + useContext yetarli. Real-time dashboard, tez-tez yangilanadigan katta ro'yxat — Zustand yaxshiroq.
Xulosa
useReducer + useContext = oddiy global state manager.
Uchta qism:
- Reducer — mantiq (qanday o'zgarish)
- Provider — state va dispatch ni tarqatish
- Custom hook — qulay interfeys
Zustand va Redux ni o'rganishdan oldin bu pattern ni tushunish — ularning ichini tushunishga yordam beradi. Ular ham xuddi shu g'oyaga asoslangan, faqat optimallashtirilgan.
Keyingi dars
22-dars: useLayoutEffect — useEffect dan farqi, qachon kerak