useState — ob'ekt va massiv state, nima uchun spread kerak
Ob'ekt state
State faqat son yoki string emas — ob'ekt ham bo'lishi mumkin.
function Profil() {
const [user, setUser] = useState({
ism: 'Jasur',
email: 'jasur@gmail.com',
yosh: 25,
});
return (
<div>
<p>{user.ism}</p>
<p>{user.email}</p>
</div>
);
}
Ob'ektni yangilash — nima uchun spread kerak?
Faqat ismni o'zgartirmoqchisiz. Shunday qilsangiz nima bo'ladi?
// ❌ Xato — email va yosh yo'qoladi!
setUser({ ism: 'Bobur' });
Nima uchun? setUser eski ob'ektni yangi ob'ekt bilan to'liq almashtiradi. { ism: 'Bobur' } — bu faqat ism bor ob'ekt. Email va yosh yo'q.
Oldin: { ism: 'Jasur', email: 'jasur@gmail.com', yosh: 25 }
Keyin: { ism: 'Bobur' } ← email va yosh yo'qoldi!
To'g'ri usul — spread operator bilan eski maydonlarni ko'chirib, faqat o'zgarganini yangilash:
// ✅ To'g'ri — eski maydonlar saqlanadi
setUser({ ...user, ism: 'Bobur' });
...user → ism: 'Jasur', email: 'jasur@gmail.com', yosh: 25
ism: 'Bobur' → ism ni ustiga yozadi
Natija: { ism: 'Bobur', email: 'jasur@gmail.com', yosh: 25 }
Amaliy misol
function ProfilTahrirlash() {
const [user, setUser] = useState({
ism: 'Jasur',
email: 'jasur@gmail.com',
shahar: 'Toshkent',
});
function ismniOzgartir(yangiIsm) {
setUser({ ...user, ism: yangiIsm });
}
function emailniOzgartir(yangiEmail) {
setUser({ ...user, email: yangiEmail });
}
return (
<div>
<input
value={user.ism}
onChange={e => ismniOzgartir(e.target.value)}
/>
<input
value={user.email}
onChange={e => emailniOzgartir(e.target.value)}
/>
<p>Shahar: {user.shahar}</p>
</div>
);
}
Yoki qisqaroq — bitta universal handler:
function ProfilTahrirlash() {
const [user, setUser] = useState({
ism: 'Jasur',
email: 'jasur@gmail.com',
shahar: 'Toshkent',
});
function ozgartir(maydon, qiymat) {
setUser({ ...user, [maydon]: qiymat });
}
return (
<div>
<input value={user.ism} onChange={e => ozgartir('ism', e.target.value)} />
<input value={user.email} onChange={e => ozgartir('email', e.target.value)} />
</div>
);
}
Massiv state
Massiv state da ham xuddi shu qoida — to'g'ridan-to'g'ri o'zgartirmang, yangi massiv yarating.
Massiv metodlari ikki turga bo'linadi:
Yangi massiv qaytaradi (✅ ishlatish mumkin):
map, filter, slice, concat, [...spread]
Asl massivni o'zgartiradi (❌ ishlatmang):
push, pop, splice, sort, reverse
Element qo'shish
const [vazifalar, setVazifalar] = useState([
{ id: 1, matn: 'React o\'rganish' },
]);
// ❌ Xato
vazifalar.push({ id: 2, matn: 'Loyiha yozish' });
// ✅ Oxiriga qo'shish
setVazifalar([...vazifalar, { id: 2, matn: 'Loyiha yozish' }]);
// ✅ Boshiga qo'shish
setVazifalar([{ id: 2, matn: 'Loyiha yozish' }, ...vazifalar]);
Element o'chirish
// ✅ id bo'yicha o'chirish
setVazifalar(vazifalar.filter(v => v.id !== ochiriladiganId));
Element yangilash
// ✅ id bo'yicha yangilash
setVazifalar(vazifalar.map(v =>
v.id === yangilanadigan.id ? { ...v, matn: yangiMatn } : v
));
To'liq misol — vazifalar ro'yxati
function VazifaIlovasi() {
const [vazifalar, setVazifalar] = useState([
{ id: 1, matn: 'Nonushta qilish', bajarildi: true },
{ id: 2, matn: 'React o\'rganish', bajarildi: false },
]);
const [yangiMatn, setYangiMatn] = useState('');
function qoshish() {
if (!yangiMatn.trim()) return;
setVazifalar([
...vazifalar,
{ id: Date.now(), matn: yangiMatn, bajarildi: false },
]);
setYangiMatn('');
}
function bajarildiToggle(id) {
setVazifalar(vazifalar.map(v =>
v.id === id ? { ...v, bajarildi: !v.bajarildi } : v
));
}
function ochirish(id) {
setVazifalar(vazifalar.filter(v => v.id !== id));
}
return (
<div>
<div>
<input
value={yangiMatn}
onChange={e => setYangiMatn(e.target.value)}
placeholder="Yangi vazifa..."
/>
<button onClick={qoshish}>Qo'shish</button>
</div>
<ul>
{vazifalar.map(v => (
<li key={v.id}>
<input
type="checkbox"
checked={v.bajarildi}
onChange={() => bajarildiToggle(v.id)}
/>
<span style={{ textDecoration: v.bajarildi ? 'line-through' : 'none' }}>
{v.matn}
</span>
<button onClick={() => ochirish(v.id)}>✕</button>
</li>
))}
</ul>
</div>
);
}
Xulosa
Ob'ekt yangilash:
setUser({ ...user, ozgarganMaydon: yangiQiymat })
└── eski maydonlar └── faqat shu o'zgaradi
Massiv yangilash:
Qo'shish: [...massiv, yangiElement]
O'chirish: massiv.filter(el => el.id !== id)
Yangilash: massiv.map(el => el.id === id ? {...el, ...yangi} : el)
Asosiy qoida: React state ni reference bo'yicha solishtiradi. Agar siz eski ob'ekt/massivni o'zgartirsangiz — React farq ko'rmaydi, ekran yangilanmaydi. Har doim yangi ob'ekt/massiv yarating.
Keyingi dars
10-dars: useEffect — nima, qachon ishlaydi, dependency array