useReducer — action, dispatch, reducer funksiya
Action nima?
Oldingi darsda dispatch({ type: 'QOSHISH', payload: ... }) yozdik. Keling, bu tushunchalarni chuqurroq ko'ramiz.
Action — "nima bo'ldi" ni tasvirlovchi oddiy ob'ekt. Xuddi xabar kabi: "foydalanuvchi qo'shish tugmasini bosdi, mana ma'lumot".
{
type: 'QOSHISH', ← nima bo'ldi (majburiy)
payload: 'Matn' ← qo'shimcha ma'lumot (ixtiyoriy)
}
type — har doim string. Odatda KATTA_HARF bilan yoziladi — bu konventsiya, majburiy emas. Lekin katta loyihalarda KATTA_HARF yozilgan action ni ko'rganingizda darhol "bu action" deb bilasiz.
payload — action bilan birga keladigan ma'lumot. Har xil nom ishlatish mumkin, lekin payload — keng tarqalgan standart.
Reducer funksiyasini chuqurroq tushunish
Reducer — switch/case bilan yoziladi. Har bir case — bitta action turi uchun javob.
function hisoblagichReducer(state, action) {
switch (action.type) {
case 'OSHIR':
// qadam bo'yicha oshirish — payload da qadam bor
return { ...state, son: state.son + action.payload };
case 'KAMAYTIR':
return { ...state, son: state.son - action.payload };
case 'NOLGA_QAYTARISH':
// payload kerak emas
return { ...state, son: 0 };
case 'QADAM_OZGARTIR':
return { ...state, qadam: action.payload };
default:
// Noma'lum action — state ni o'zgartirmay qaytarish
// Bu muhim — xato action yuborilganda state buzilmasin
return state;
}
}
function Hisoblagich() {
const [state, dispatch] = useReducer(hisoblagichReducer, { son: 0, qadam: 1 });
return (
<div>
<p>Son: {state.son}</p>
<button onClick={() => dispatch({ type: 'OSHIR', payload: state.qadam })}>
+{state.qadam}
</button>
<button onClick={() => dispatch({ type: 'KAMAYTIR', payload: state.qadam })}>
-{state.qadam}
</button>
<button onClick={() => dispatch({ type: 'NOLGA_QAYTARISH' })}>
Nolga qaytarish
</button>
<label>
Qadam:
<input
type="number"
value={state.qadam}
onChange={e => dispatch({ type: 'QADAM_OZGARTIR', payload: +e.target.value })}
/>
</label>
</div>
);
}
Komponent faqat "qaysi tugma bosildi, qanday qiymat bilan" deydi. Hisoblash mantiqi — reducerda.
Murakkab state — forma misoli
useReducer ning kuchi murakkab formalar bilan ishlashda ko'rinadi. Forma yuborilayotganda bir vaqtda bir nechta state o'zgaradi: loading boshlanadi, xato tozalanadi. Muvaffaqiyatda forma tozalanadi. Xatoda loading to'xtaydi, xato ko'rsatiladi.
const boshlangich = {
ism: '',
email: '',
yuklanmoqda: false,
xato: null,
muvaffaqiyat: false,
};
function formaReducer(state, action) {
switch (action.type) {
case 'MAYDON_OZGARTIR':
return {
...state,
[action.payload.maydon]: action.payload.qiymat,
xato: null, // yozayotganda xatoni tozala
};
case 'YUBORISH_BOSHLANDI':
// bir vaqtda ikki narsa o'zgaradi
return { ...state, yuklanmoqda: true, xato: null };
case 'YUBORISH_MUVAFFAQIYAT':
return { ...boshlangich, muvaffaqiyat: true }; // formani tozala
case 'YUBORISH_XATO':
return { ...state, yuklanmoqda: false, xato: action.payload };
default:
return state;
}
}
useState bilan bu to'rtta alohida set funksiyasi bo'lardi. useReducer bilan — bitta dispatch, bir joyda boshqariladi.
function Forma() {
const [state, dispatch] = useReducer(formaReducer, boshlangich);
async function yuborish(e) {
e.preventDefault();
dispatch({ type: 'YUBORISH_BOSHLANDI' });
try {
await fetch('/api/register', {
method: 'POST',
body: JSON.stringify({ ism: state.ism, email: state.email }),
});
dispatch({ type: 'YUBORISH_MUVAFFAQIYAT' });
} catch (err) {
dispatch({ type: 'YUBORISH_XATO', payload: err.message });
}
}
if (state.muvaffaqiyat) return <p>✅ Muvaffaqiyatli ro'yxatdan o'tdingiz!</p>;
return (
<form onSubmit={yuborish}>
{state.xato && <p style={{ color: 'red' }}>{state.xato}</p>}
<input
value={state.ism}
onChange={e => dispatch({
type: 'MAYDON_OZGARTIR',
payload: { maydon: 'ism', qiymat: e.target.value },
})}
placeholder="Ism"
/>
<input
value={state.email}
onChange={e => dispatch({
type: 'MAYDON_OZGARTIR',
payload: { maydon: 'email', qiymat: e.target.value },
})}
placeholder="Email"
/>
<button disabled={state.yuklanmoqda}>
{state.yuklanmoqda ? 'Yuborilmoqda...' : 'Ro\'yxatdan o\'tish'}
</button>
</form>
);
}
Reducer ni alohida faylga chiqarish
Reducer alohida faylda bo'lsa — uni alohida test qilish mumkin. Komponent faqat UI bilan shug'ullanadi.
src/
├── reducers/
│ └── vazifaReducer.js ← mantiq shu yerda
└── components/
└── VazifaIlovasi.jsx ← faqat UI
// reducers/vazifaReducer.js
export const boshlangich = [];
export function vazifaReducer(state, action) {
switch (action.type) {
case 'QOSHISH':
return [...state, { id: Date.now(), matn: action.payload, bajarildi: false }];
case 'OCHIRISH':
return state.filter(v => v.id !== action.payload);
case 'TOGGLE':
return state.map(v =>
v.id === action.payload ? { ...v, bajarildi: !v.bajarildi } : v
);
default:
return state;
}
}
// components/VazifaIlovasi.jsx
import { useReducer } from 'react';
import { vazifaReducer, boshlangich } from '../reducers/vazifaReducer';
function VazifaIlovasi() {
const [vazifalar, dispatch] = useReducer(vazifaReducer, boshlangich);
// ...
}
Xulosa
Action: { type: 'AMAL', payload: ... }
"nima bo'ldi" + "qo'shimcha ma'lumot"
Dispatch: dispatch(action)
"mana, shu bo'ldi"
Reducer: (state, action) => yangiState
"shu bo'lganda, shunday o'zgartir"
type— KATTA_HARF konventsiyadefault— har doim bo'lishi kerak- Reducer — sof funksiya, alohida faylda saqlash mumkin
- Bir vaqtda bir nechta state o'zgarishi kerak bo'lsa —
useReducerkuchliroq
Keyingi dars
21-dars: useReducer + useContext — o'z state manager ini yozish