11.4-bob: State, hodisalar, shartli render, ro'yxatlar va keys
11-QISM — Frontend: React · 4-mavzu
1. Kirish va motivatsiya
11.2-bobda komponent va props'ni, 11.3-bobda Vite loyihasini o'rgandik — lekin ilovamiz hali jonsiz. Foydalanuvchi tugmani bossa, matn yozsa, hech narsa o'zgarmaydi. Sababi oddiy: komponentlarimizda xotira yo'q. Ular faqat props orqali kelgan statik ma'lumotni ko'rsatadi, xolos. Endi React'ning eng sehrli, eng markaziy qismiga — statega — o'tamiz. Aynan shu bobda 11.1-bobdagi butun og'riq (har o'zgarishda qo'lda render() chaqirish, UI va ma'lumotni qo'lda sinxronlash) butunlay yo'qoladi, va UI = f(state) formulasi jonlanadi.
State — komponentning "xotirasi": vaqt o'tishi bilan o'zgaradigan, va o'zgarganda UI'ni avtomatik yangilaydigan ma'lumot. Tugma necha marta bosilgani, formadagi matn, modal ochiqmi, ro'yxatdagi elementlar — bularning hammasi state. React'ning asosiy va'dasi shu: siz faqat state'ni o'zgartirasiz, React UI'ni o'zi yangilaydi (DOM'ga qo'lda teginmaysiz, render() chaqirmaysiz, qaysi joyni yangilashni eslab qolmaysiz). Lekin bu sehr ortida aniq qoidalar bor — va aynan shu qoidalarni chuqur tushunmaslik junior dasturchilarning eng katta xatolar manbai. Shuning uchun bu bobni biz odatdagidan ham batafsilroq, har bir holat uchun alohida kod bilan yozamiz.
Bu bob to'rt katta mavzuni qamraydi: State (useState to'liq anatomiyasi, state — snapshot ekani, asinxron/batched yangilanish, updater funksiya, immutability — obyekt va massivni to'g'ri yangilash), Hodisalar (event handlers, argument uzatish, synthetic events, controlled inputs — forma asoslari), Shartli render (if, ternary, &&, element o'zgaruvchi va tuzoqlari), va Ro'yxatlar + key (map, key chuqur — nega kerak, nega index xato), hamda lifting state up (state'ni komponentlar o'rtasida ulashish). Bundan tashqari, senior bo'lish uchun shart bo'lgan tushunchalar — state snapshot modeli, batching, lazy initial state, immutability'ning chuqur sabablari — ham qamraladi.
O'xshatish: State — bu komponentning fotosurati va xotira daftarchasi birgalikda. Tasavvur qil: har "render" — bu komponentning bir lahzalik fotosurati (snapshot). Fotosuratda state qiymati qotib turadi (o'sha lahzada nima bo'lsa, shu). Siz state'ni o'zgartirganda — eski suratni tahrirlamaysiz, balki React'dan yangi surat olishini so'raysiz (re-render). React yangi qiymat bilan komponentni qaytadan "suratga oladi". Mana shuning uchun React'da
count = count + 1deb yozmaysiz (eski suratni o'zgartirib bo'lmaydi) —setCount(count + 1)deb yangi surat buyurtma qilasiz. Va daftarcha (state) — React'ning qo'lida saqlanadi: komponent qayta "tug'ilganda" (re-render), React unga eski daftarchani qaytarib beradi ("oldingi qiymating shu edi"). Bu model —useStatening butun xatti-harakatini izohlaydi.
Nega muhim?
- React'ning yuragi — state'siz interaktiv UI yo'q; har tugma, forma, ro'yxat — state.
- Eng ko'p xato shu yerda — snapshot, immutability, batching tushunilmasa — "nega yangilanmayapti?" degan tuzoqlarga tushasiz.
- Forma va ma'lumot — controlled inputs (11.10 RHF), API ma'lumoti 12.4-bob — hammasi state ustiga quriladi.
- Deklarativ tafakkur —
UI = f(state)ni amalda his qilish — barcha keyingi boblarning poydevori.
2. Nazariya — chuqur tushuntirish
2.1. State nima va nega oddiy o'zgaruvchi yetmaydi
MUAMMO: nega oddiy o'zgaruvchi (let count = 0) React'da ishlamaydi?
function Counter() {
let count = 0; // oddiy o'zgaruvchi
return <button onClick={() => {
count = count + 1; // o'zgaradi-yu...
console.log(count); // konsolda 1, 2, 3... (o'zgaryapti)
}}>{count}</button>; // ...lekin EKRAN o'zgarmaydi (0 qoladi)
}
2 SABAB:
1. RE-RENDER YO'Q — oddiy o'zgaruvchini o'zgartirish React'ni "xabardor" qilmaydi
(React UI'ni qachon yangilashni bilmaydi ekran eski qoladi)
2. XOTIRA YO'Q — komponent qayta render bo'lsa, funksiya BOSHIDAN ishlaydi
let count = 0 yana 0 ga "tiklanadi" (oldingi qiymat yo'qoladi — 11.2: 2.2)
YECHIM — useState:
const [count, setCount] = useState(0); // React xotirada saqlaydi + re-render qiladiState — komponentning vaqt o'tishi bilan o'zgaradigan va o'zgarganda UI'ni yangilaydigan ma'lumoti. Nega oddiy o'zgaruvchi (
let count = 0) yetmaydi? Ikki sabab: (1) re-render yo'q — oddiy o'zgaruvchini o'zgartirsangiz, React buni bilmaydi, shuning uchun UI'ni yangilamaydi (ekran eski qoladi — konsolda qiymat o'zgarsa ham); (2) xotira yo'q — komponent qayta render bo'lganda funksiya boshidan ishlaydi (11.2: 2.2), shuning uchunlet count = 0yana 0 ga tiklanadi (oldingi qiymat yo'qoladi).useStateikkala muammoni hal qiladi: React qiymatni o'z xotirasida (komponent renderlari orasida) saqlaydi, va state o'zgarganda komponentni qayta render qiladi. Mana shuning uchun React'da xotira kerak bo'lgan har qanday ma'lumot —useState(yoki boshqa hook) orqali saqlanadi, oddiy o'zgaruvchi orqali emas. Oddiy o'zgaruvchi faqat bitta render ichida vaqtincha hisob-kitob uchun ishlatiladi.
2.2. useState anatomiyasi — to'liq tahlil
const [count, setCount] = useState(0);
// │ │ │
// │ │ └─ boshlang'ich qiymat (faqat BIRINCHI render'da)
// │ └─ YANGILOVCHI funksiya (state'ni o'zgartiradi + re-render)
// └─ joriy QIYMAT (shu render'dagi state)
useState QAYTARADI: [qiymat, yangilovchiFunksiya] (massiv — destructuring bilan olamiz — 2.8 JS)
NOMLASH KONVENSIYASI: [x, setX] — yangilovchi "set" + bosh harf
const [name, setName] = useState(""); // string
const [age, setAge] = useState(0); // number
const [isOpen, setIsOpen] = useState(false); // boolean
const [user, setUser] = useState(null); // obyekt (boshlang'ich null)
const [items, setItems] = useState([]); // massiv (boshlang'ich bo'sh)
useState — "hook" (React funksiyasi); FAQAT komponent ICHIDA, TEPADA chaqiriladi (11.5: Rules)
boshlang'ich qiymat FAQAT birinchi render'da ishlatiladi (keyin e'tiborsiz)
useState— eng asosiy React hook'i; u state e'lon qiladi va massiv qaytaradi:[joriyQiymat, yangilovchiFunksiya]. Destructuring bilan ikkisini olamiz (2.8 JS):const [count, setCount] = useState(0). Uch element:count(shu render'dagi joriy qiymat),setCount(state'ni o'zgartiradigan va re-render keltiradigan funksiya),useState(0)dagi0(boshlang'ich qiymat — faqat birinchi render'da ishlatiladi, keyingi renderlarda e'tiborsiz qoldiriladi). Nomlash konvensiyasi:[x, setX](yangilovchi "set" prefiksi bilan). Boshlang'ich qiymat har qanday tur bo'lishi mumkin: string (""), number (0), boolean (false), obyekt/massiv, yokinull.useState— hook: u faqat komponent ichida va funksiyaning eng tepasida chaqiriladi (shart/tsikl ichida emas — bu "Rules of Hooks", 11.5'da chuqur). Hozircha esda tut: state e'lon qilish har doim komponent boshida, to'g'ridan-to'g'ri.
2.3. State — "snapshot" (har render o'z qiymatiga ega)
ENG MUHIM TUSHUNCHA: har render — state'ning "lahzalik surati" (snapshot)
Har render'da count — O'SHA render uchun QOTGAN qiymat (o'zgarmas konstanta kabi)
function Counter() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1); // count = 0 (BU render'da) setCount(1)
setCount(count + 1); // count HALI HAM 0 (bir xil render) setCount(1)
setCount(count + 1); // count HALI HAM 0 setCount(1)
// Natija: 3 emas, 1! (count bu render davomida 0 bo'lib QOTGAN)
}
return <button onClick={handleClick}>{count}</button>;
}
┌─────────────────────────────────────────────────────────────┐
│ Render #1: count = 0 (handleClick ichida count har doim 0) │
│ setCount(1) uch marta = "keyingi render'da 1 bo'lsin" │
│ Render #2: count = 1 (yangi snapshot) │
└─────────────────────────────────────────────────────────────┘
count o'zgaruvchisi BIR render ichida HECH QACHON o'zgarmaydi (qotgan surat)
setCount darrov o'zgartirmaydi — "keyingi render uchun" rejalashtiradi (2.5)State — snapshot — React'ning eng muhim va eng ko'p chalkashtiriladigan tushunchasi. Har bir render'da state o'zgaruvchisi (
count) — o'sha render uchun qotib qolgan qiymat (xuddiconstkabi, render davomida o'zgarmaydi). Misolda bitta handler ichidasetCount(count + 1)ni uch marta chaqirsak ham natija 3 emas, 1 bo'ladi — chunkicountshu render davomida 0 bo'lib qotgan, har uch chaqiruv ham "keyingi render'da 1 bo'lsin" deydi. Ikki hal qiluvchi xulosa: (1) state o'zgaruvchisi bir render ichida hech qachon o'zgarmaydi — u o'sha render'ning "lahzalik surati"; (2)setCountqiymatni darrov o'zgartirmaydi — u keyingi render uchun yangi qiymatni rejalashtiradi (2.5 — asinxron). Agar bitta handler ichida state'ni ketma-ket bir necha marta yangilash kerak bo'lsa — updater funksiya ishlatasiz 2.6-bob. Bu modelni tushunsangiz — "nega state darrov yangilanmayapti?" degan eng keng tuzoqdan butunlay qutulasiz.
2.4. State yangilash re-render keltiradi (UI = f(state) amalda)
JARAYON (state o'zgardi ekran yangilandi):
1. setCount(5) chaqirildi
2. React: "count state'i 5 bo'ladi" deb belgilaydi (rejalashtiradi)
3. React komponent funksiyasini QAYTA chaqiradi (re-render)
4. Bu safar useState 5 ni qaytaradi (yangi snapshot — 2.3)
5. Yangi JSX hosil bo'ladi Virtual DOM diffing (11.2: 2.1)
6. Faqat o'zgargan qism haqiqiy DOM'ga yoziladi ekran yangilandi
┌──────────────┐ setCount ┌──────────────┐ re-render ┌──────────┐
│ state o'zgardi│ ───────────► │ React xabardor│ ───────────► │ yangi UI │
└──────────────┘ └──────────────┘ └──────────┘
11.1: 2.9 dagi QO'LDA render() YO'QOLDI — React O'ZI qiladi (UI = f(state))
Siz faqat "ma'lumot qanday" ni boshqarasiz; "qanday ko'rsatish" — React'daState yangilash re-render — React'ning markaziy mexanizmi va
UI = f(state)ning amaliy ko'rinishi.setCount(5)chaqirilganda: React state'ni yangilashni belgilaydi komponent funksiyasini qayta chaqiradi (re-render) bu safaruseStateyangi qiymatni (5) qaytaradi (2.3 snapshot) yangi JSX hosil bo'ladi Virtual DOM diffing (11.2: 2.1) faqat o'zgargan qism haqiqiy DOM'ga yoziladi ekran yangilanadi. Mana 11.1: 2.9 dagi butun og'riqning yechimi: vanilla'da biz qo'ldarender()chaqirar, qaysi DOM bo'lagini yangilashni eslab qolar edik — endi bularning hech biri yo'q. Siz faqat state'ni (ma'lumotni) o'zgartirasiz, "qanday ko'rsatish"ni React o'zi hal qiladi. Bu — deklarativ dasturlashning kuchi: siz nima kerakligini aytasiz, qanday qilishni React biladi. Butun React shu g'oya atrofida quriladi.
2.5. State yangilanishi — asinxron va batched (to'plamli)
setX DARROV o'zgartirmaydi — re-render'ni REJALASHTIRADI (asinxron)
BATCHING — bir hodisa ichidagi BARCHA setX'lar TO'PLANIB, BITTA re-render qiladi
function handleClick() {
setCount(count + 1); // rejalashtirildi
setName("Ali"); // rejalashtirildi
setActive(true); // rejalashtirildi
// React BARCHASINI to'plab, BITTA re-render qiladi (3 ta emas — samarali!)
console.log(count); // HALI ESKI qiymat (re-render hali bo'lgani yo'q)
}
┌────────────────────────────────────────────────────────────┐
│ 3 ta setX React kutadi hammasini birlashtiradi 1 render│
│ (har setX'da alohida render bo'lganda — 3 marta sekin bo'lardi)│
└────────────────────────────────────────────────────────────┘
setX'dan KEYIN darrov state'ni o'qisangiz — ESKI qiymat (yangisi keyingi render'da)
React 18+ : batching HAMMA joyda (hodisa, promise, setTimeout — avtomatik)Asinxron va batched yangilanish —
setXstate'ni darrov o'zgartirmaydi, balki re-render'ni rejalashtiradi (asinxron). Bundan tashqari React batching (to'plamlash) qiladi: bitta hodisa (event handler) ichidagi barchasetXchaqiruvlari to'planib, bitta re-render qilinadi (har biriga alohida render emas — bu samaralilik uchun). Shuning uchunsetCount(...)dan keyin darrovconsole.log(count)qilsangiz — eski qiymatni ko'rasiz (yangisi keyingi render'da paydo bo'ladi — 2.3 snapshot bilan bog'liq). Ikki muhim nuqta: (1) state yangilanishini "darrov" deb o'ylama — u keyingi render'da kuchga kiradi; (2) React 18+ da batching hamma joyda ishlaydi (hodisa, Promise,setTimeout, native event — avtomatik; ilgari faqat React hodisalarida edi). Agar state'ning yangi qiymatiga handler ichida darrov muhtoj bo'lsangiz — o'zgaruvchini alohida hisoblab ishlat (const next = count + 1; setCount(next); foo(next);). Bu mexanizm React ilovasini tez va bashoratli qiladi.
2.6. Updater funksiya — setX(prev => ...) qachon va nega
MUAMMO 2.3-bob: bitta handler'da ketma-ket yangilash count'ni "qotgan" ko'radi
count'ga tayanish (snapshot — har uchchovi 0 ko'radi):
setCount(count + 1); // 0 + 1
setCount(count + 1); // 0 + 1 (count hali 0)
setCount(count + 1); // 0 + 1 natija: 1 (3 emas!)
UPDATER FUNKSIYA — React "oldingi" qiymatni beradi (navbatda yangilanadi):
setCount(prev => prev + 1); // prev = 0 1
setCount(prev => prev + 1); // prev = 1 2 (React navbatda hisoblaydi)
setCount(prev => prev + 1); // prev = 2 3 natija: 3
QACHON updater (prev =>) ishlatish:
Yangi qiymat ESKISIGA bog'liq bo'lsa (count + 1, [...prev, x], !prev)
Bitta handler'da ketma-ket bir necha marta yangilaganda
Asinxron (setTimeout, promise) ichida yangilaganda (eski snapshot tuzog'idan qochish)
Qoida: "oldingi qiymatdan kelib chiqsangiz — updater funksiya ishlating"Updater funksiya —
setX(prev => yangi)shakli, bunda React sizga eng so'nggi (navbatdagi) qiymatniprevorqali beradi. 2.3 dagi muammoni hal qiladi:setCount(count + 1)snapshot tufaylicountni qotgan ko'radi, lekinsetCount(prev => prev + 1)— React har chaqiruvda oldingi natijani uzatadi, shuning uchun ketma-ket uch chaqiruv 0123 ni to'g'ri hisoblaydi. Qachon updater funksiya ishlatish kerak: (1) yangi qiymat eskisiga bog'liq bo'lsa (count + 1,[...prev, item],!prev— toggle); (2) bitta handler'da ketma-ket bir necha marta yangilasangiz; (3) asinxron kod (setTimeout, Promise, debounce) ichida yangilasangiz — u yerda snapshot eskirgan bo'lishi mumkin,prevesa har doim yangi. Oltin qoida: "oldingi qiymatdan kelib chiqsangiz — updater funksiya ishlat" (prev =>). Bevosita yangi qiymat berayotgan bo'lsangiz (setName("Ali")— eskiga bog'liq emas) — oddiy shakl yetadi. Ko'p tajribali dasturchilar har doim updater shaklini afzal ko'radi (xavfsizroq).
2.7. State immutability — mutatsiya qilma, yangi yarat
QOIDA: state'ni HECH QACHON to'g'ridan o'zgartirma (mutate qilma) — YANGI nusxa yarat
MUTATSIYA (state'ni joyida o'zgartirish — React buni "ko'rmaydi"):
const [user, setUser] = useState({ name: "Ali", age: 25 });
user.age = 26; // obyektni joyida o'zgartirdik
setUser(user); // AYNI obyekt (havola bir xil) React: "o'zgarmagan" re-render YO'Q
YANGI OBYEKT (spread bilan nusxa + o'zgartirish):
setUser({ ...user, age: 26 }); // yangi obyekt (yangi havola) React: "o'zgardi" re-render
NEGA: React eski va yangi state'ni HAVOLA (reference) bo'yicha solishtiradi (===)
- bir xil havola "o'zgarmagan" deb hisoblaydi (re-render yo'q)
- yangi havola "o'zgargan" re-render
┌────────────────────────────────────────────────────────────┐
│ Primitiv (number, string, boolean): setX(yangi) — muammosiz │
│ Obyekt/massiv: HAR DOIM yangi nusxa yarat ({...}, [...]) │
└────────────────────────────────────────────────────────────┘
Immutability — React performance (===) va bashoratlilik (predictable) asosiImmutability (o'zgarmaslik) — React'da state'ni hech qachon to'g'ridan-to'g'ri o'zgartirmaslik (mutate qilmaslik), o'rniga yangi nusxa yaratish qoidasi. Nega: React eski va yangi state'ni havola (reference) bo'yicha solishtiradi (
===— yuzaki/shallow taqqoslash). Agar obyektni joyida o'zgartirsangiz (user.age = 26) va aynan o'sha obyektnisetUser(user)bilan bersangiz — havola bir xil qoladi, React "o'zgarmagan" deb hisoblaydi va re-render qilmaydi (UI eskirib qoladi). To'g'ri yo'l: yangi obyekt yaratish (setUser({ ...user, age: 26 })) — yangi havola React o'zgarishni ko'radi re-render. Primitiv qiymatlar (number, string, boolean) bilan bu muammo yo'q (setCount(5)— muammosiz), lekin obyekt va massiv bilan har doim yangi nusxa ({...},[...]) yaratasiz. Immutability tasodifiy qoida emas: u React'ning tez taqqoslashi (===,memo— 11.11),useEffectbog'liqliklari 11.5-bob, Redux 12.2-bob — barchasining asosi. State'ni o'zgarmas deb hisoblash — bashoratli, xatosiz ilovaning kaliti.
2.8. Obyektni state'da yangilash (spread, ichma-ich)
YASSI OBYEKT — spread (...) bilan nusxalab, kerakli maydonni almashtir:
const [form, setForm] = useState({ name: "", email: "", age: 0 });
setForm({ ...form, name: "Ali" }); // faqat name o'zgardi, qolgani saqlanadi
setForm(prev => ({ ...prev, age: 26 })); // updater bilan (xavfsizroq — 2.6)
ICHMA-ICH (nested) OBYEKT — har QATLAMNI nusxala (chuqurroq):
const [user, setUser] = useState({
name: "Ali",
address: { city: "Toshkent", street: "Navoiy" }
});
// setUser({ ...user, address: { city: "Samarqand" } }) street YO'QOLADI!
// ichki obyektni ham nusxala:
setUser({
...user,
address: { ...user.address, city: "Samarqand" } // street saqlanadi
});
Chuqur ichma-ich state og'riqli state'ni YASSI tut yoki Immer/useReducer (11.6)
Dinamik maydon (forma): setForm({ ...form, [e.target.name]: e.target.value }) — 2.11Obyektni state'da yangilash — immutability 2.7-bob tufayli yangi obyekt yaratamiz. Yassi (flat) obyekt: spread bilan nusxalab, kerakli maydonni almashtirasiz:
setForm({ ...form, name: "Ali" })(qolgan maydonlar saqlanadi). Updater bilan xavfsizroq:setForm(prev => ({ ...prev, age: 26 }))(e'tibor: obyekt qaytaruvchi strelka funksiyada({...})— qavs majburiy). Ichma-ich (nested) obyekt — bu yerda tuzoq bor: agar faqat tashqi qatlamni nusxalasangiz ({ ...user, address: { city: ... } }), ichki obyektning boshqa maydonlari (street) yo'qoladi; shuning uchun har qatlamni nusxalash kerak:{ ...user, address: { ...user.address, city: "Samarqand" } }. Chuqur ichma-ich state qo'lda nusxalash og'riqli bo'ladi — ikki yechim: (1) state'ni yassi (flat) tut (chuqur joylashtirmadan saqlan); (2)Immerkutubxonasi (mutatsiya yozuvini immutable qiladi) yokiuseReducer11.6-bob. Dinamik maydon (forma) uchun computed property:{ ...form, [e.target.name]: e.target.value }2.11-bob.
2.9. Massivni state'da yangilash (qo'shish, o'chirish, yangilash)
QOIDA: massivni MUTATSIYA qiluvchi metodlar TAQIQ (push, pop, splice, sort, reverse)
ular joyida o'zgartiradi (havola bir xil re-render yo'q — 2.7)
RUXSAT: yangi massiv qaytaruvchilar ([...], map, filter, slice, concat)
const [items, setItems] = useState([{id:1, text:"A"}, {id:2, text:"B"}]);
QO'SHISH (oxiriga / boshiga):
setItems([...items, { id: 3, text: "C" }]); // oxiriga (push o'rniga)
setItems([{ id: 0, text: "Z" }, ...items]); // boshiga (unshift o'rniga)
O'CHIRISH (id bo'yicha — filter):
setItems(items.filter(item => item.id !== 2)); // id=2 dan tashqari hammasi
YANGILASH (bitta elementni — map):
setItems(items.map(item =>
item.id === 1 ? { ...item, text: "Yangi A" } : item // id=1 ni almashtir, qolgani o'z holida
));
TARTIBLASH (nusxa olib, keyin sort — original'ni buzmaslik):
setItems([...items].sort((a, b) => a.text.localeCompare(b.text))); // [...] nusxa MAJBURIY
push/splice/sort — original'ni buzadi AVVAL [...] bilan nusxa olMassivni state'da yangilash — immutability 2.7-bob tufayli mutatsiya qiluvchi metodlar (
push,pop,splice,sort,reverse) taqiqlanadi (ular massivni joyida o'zgartiradi, havola bir xil qoladi re-render bo'lmaydi). O'rniga yangi massiv qaytaruvchi metodlar: qo'shish —[...items, yangi](oxiriga,pusho'rniga) yoki[yangi, ...items](boshiga); o'chirish —items.filter(x => x.id !== id)(shartga mos kelmaydiganlarni qoldiradi); yangilash —items.map(x => x.id === id ? {...x, ...yangilanish} : x)(mos kelganini almashtiradi, qolganini o'z holida qoldiradi); tartiblash —[...items].sort(...)(e'tibor:sortoriginal'ni buzadi, shuning uchun avval[...]bilan nusxa ol). Bu naqshlar — React'da massiv state'i bilan ishlashning standarti, ularni yoddan bilishing kerak (ro'yxat, savat, vazifalar — hammasi shu).map/filterichidagi obyektlarni ham mutatsiya qilma — yangi obyekt qaytar ({...x, ...}).
2.10. Hodisalar (event handlers) — to'g'ri ulash va argument uzatish
HODISA ULASH — funksiyani UZAT (chaqirma!):
onClick={handleClick} // funksiya HAVOLASI (React kerak bo'lganda chaqiradi)
onClick={handleClick()} // funksiyani CHAQIRDIK natijasi prop'ga (render'da darrov ishlaydi!)
ARGUMENT UZATISH — strelka funksiya bilan o'rab:
onClick={() => handleDelete(id)} // o'ralgan bosilganda handleDelete(id) chaqiriladi
onClick={handleDelete(id)} // darrov chaqiriladi (render paytida — xato)
KENG TARQALGAN HODISALAR:
onClick (tugma) | onChange (input/select) | onSubmit (forma) | onInput
onKeyDown/onKeyUp (klaviatura) | onMouseEnter/Leave | onFocus/onBlur
EVENT OBYEKT (SyntheticEvent — React o'rovi):
function handleChange(e) {
e.target.value // input qiymati
e.preventDefault() // standart harakatni to'xtat (forma — 2.11)
e.stopPropagation() // bubbling'ni to'xtat (11.1: 2.6)
}
React hodisasi — SyntheticEvent (barcha brauzerda bir xil ishlaydi; ostida native event)Hodisalar (event handlers) — foydalanuvchi harakatlariga javob. Eng keng xato — funksiyani chaqirib qo'yish:
onClick={handleClick()}funksiyani render paytida darrov chaqiradi (natijasi prop'ga tushadi) — to'g'risionClick={handleClick}(funksiya havolasi, React kerak bo'lganda chaqiradi). Argument uzatish kerak bo'lsa — strelka funksiya bilan o'ra:onClick={() => handleDelete(id)}(bosilgandahandleDelete(id)ishlaydi);onClick={handleDelete(id)}esa darrov chaqiriladi (xato). Keng hodisalar:onClick,onChange(input/select),onSubmit(forma),onKeyDown,onMouseEnter,onFocus/onBlur. Handler event obyekt (e) oladi — bu SyntheticEvent (React'ning barcha brauzerda bir xil ishlaydigan o'rovi, ostida native event — 11.1: 2.6):e.target.value(input qiymati),e.preventDefault()(standart harakatni to'xtat — 2.11),e.stopPropagation(). React hodisalari camelCase (onClick,onclickemas — 11.2: 2.5) va event delegation orqali samarali ishlaydi (React barcha hodisalarni root'da tinglaydi).
2.11. Controlled inputs — state bilan boshqariladigan forma
CONTROLLED INPUT — input qiymati STATE'da yashaydi (React — "yagona haqiqat manbai"):
const [name, setName] = useState("");
<input
value={name} // qiymat state'dan keladi (React boshqaradi)
onChange={e => setName(e.target.value)} // har bosishda state yangilanadi
/>
IKKI TOMONLAMA BOG'LANISH (jonli aylana):
foydalanuvchi yozadi onChange setName re-render value yangilanadi ekran
┌─────────────────────────────────────────────────────────┐
│ value (state input) + onChange (input state) │
│ input HAR DOIM state'ni aks ettiradi (sinxron) │
└─────────────────────────────────────────────────────────┘
TURLI INPUT TURLARI:
text/textarea: value={x} onChange={e => setX(e.target.value)}
checkbox: checked={x} onChange={e => setX(e.target.checked)}
select: value={x} onChange={e => setX(e.target.value)}
number: value={x} onChange={e => setX(Number(e.target.value))}
value bersangiz, onChange ham BERISH SHART (aks holda "read-only" input — yozib bo'lmaydi)
Controlled — validatsiya, shartli o'chirish, formatlash oson (11.10 RHF buni soddalashtiradi)Controlled input — input qiymati state'da yashaydigan forma elementi (React — "yagona haqiqat manbai", single source of truth). Ikki bog'lanish:
value={name}(qiymat state'dan inputga) +onChange={e => setName(e.target.value)}(har o'zgarishda input'dan state'ga). Bu ikki tomonlama jonli aylana: foydalanuvchi yozadionChangesetNamere-rendervalueyangilanadi ekran. Shuning uchun input har doim state'ni aks ettiradi (sinxron). Turli input turlari biroz farq qiladi: text/textarea/select —value+e.target.value; checkbox —checked+e.target.checked(boolean); number —Number(e.target.value). Ikki muhim qoida: (1)valuebersangiz,onChangeham berish shart — aks holda input "read-only" bo'lib qoladi (yozib bo'lmaydi, React ogohlantiradi); (2) controlled input validatsiya, shartli o'chirish, jonli formatlash (telefon, narx)ni osonlashtiradi — chunki qiymat doim sizning qo'lingda. Katta formalar uchun React Hook Form bu naqshni soddalashtiradi 11.10-bob.
2.11a. Controlled vs uncontrolled — ref bilan boshqarilmaydigan input
CONTROLLED 2.11-bob: qiymat STATE'da — React "yagona haqiqat manbai" (odatiy tanlov)
<input value={name} onChange={e => setName(e.target.value)} />
UNCONTROLLED: qiymat DOM'ning O'ZIDA yashaydi — React tinglamaydi;
kerak bo'lganda ref orqali O'QIYMIZ (masalan, submit paytida)
const inputRef = useRef(null); // useRef — 11.5
<input ref={inputRef} defaultValue="Ali" /> // defaultValue (value EMAS), ref
// submit'da: inputRef.current.value hozirgi qiymatni O'QIYMIZ
FARQ:
controlled har bosishda re-render; qiymat doim state'da; validatsiya/formatlash oson
uncontrolled re-render yo'q; qiymat DOM'da; faqat kerak bo'lganda o'qiladi
value + onChange = controlled; defaultValue + ref = uncontrolled (ikkovini ARALASHTIRMA)
AMALIYOT: deyarli har doim controlled ishlat (bashoratli, boshqariladigan);
uncontrolled — faqat oddiy holat, uchinchi tomon DOM kutubxonasi, yoki fayl input (<input type="file">)Controlled vs uncontrolled — React'da forma inputining ikki yondashuvi. Controlled 2.11-bob — qiymat state'da yashaydi, React uni to'liq boshqaradi (
value+onChange); bu odatiy va tavsiya etilgan tanlov. Uncontrolled — qiymat DOM elementining o'zida qoladi, React uni tinglamaydi; siz qiymatga kerak bo'lganda (masalan, submit paytida) ref orqali kirasiz:const inputRef = useRef(null)<input ref={inputRef} defaultValue="Ali" />inputRef.current.value(useRef11.5'da chuqur). E'tibor: uncontrolled inputdavalueemas,defaultValueishlatiladi (faqat boshlang'ich qiymat, keyin DOM o'zi boshqaradi). Asosiy farq: controlled input har bosishda re-render qiladi (qiymat doim state'da — validatsiya, jonli formatlash, shartli o'chirish oson), uncontrolled esa re-render qilmaydi (qiymat faqat kerak bo'lganda o'qiladi). Ikkovini aralashtirmang (valuevadefaultValueni birga bermang — 2-bo'lim, Xato 4). Amaliyotda deyarli har doim controlled ishlatiladi (bashoratli, React boshqaruvida); uncontrolled — faqat juda oddiy holatlar, uchinchi tomon DOM kutubxonalari, yoki<input type="file">(fayl input har doim uncontrolled — brauzer xavfsizligi tufayli).
2.12. Shartli render — barcha usullar va tuzoqlar
1. TERNARY (ikki variant — eng keng):
{isLoggedIn ? <Profil /> : <Kirish />}
2. && (faqat bitta holat — "bor yoki yo'q"):
{error && <p className="error">{error}</p>} // error bo'lsa ko'rsat, bo'lmasa hech narsa
{items.length > 0 && <List items={items} />}
3. ELEMENT O'ZGARUVCHI (murakkab mantiq — return'dan oldin):
let content;
if (loading) content = <Spinner />;
else if (error) content = <Error />;
else content = <Data data={data} />;
return <div>{content}</div>;
4. null QAYTARISH (komponent hech narsa ko'rsatmaslik):
if (!visible) return null; // hech narsa render qilmaydi
&& TUZOG'I — raqam 0:
{items.length && <List />} // length=0 bo'lsa EKRANDA "0" chiqadi! (0 — falsy, lekin render bo'ladi)
{items.length > 0 && <List />} // aniq boolean shart
{!!items.length && <List />} // yoki boolean'ga majburlash
if/for JSX {} ICHIDA ishlamaydi (11.2: 2.5) ternary/&&/element o'zgaruvchiShartli render — ma'lumotga qarab turli UI ko'rsatish. To'rt asosiy usul: (1) ternary — ikki variant orasida (
{isLoggedIn ? <Profil/> : <Kirish/>}); (2)&&— bor-yo'qligi ({error && <p>{error}</p>}— error bo'lsa ko'rsat, bo'lmasa hech narsa); (3) element o'zgaruvchi — murakkab mantiq uchunreturn'dan oldinif/elsebilan o'zgaruvchiga JSX yig'asiz (loading/error/data holatlari uchun ideal — toza JSX); (4)return null— komponent hech narsa render qilmasligi.&&tuzog'i (eng keng xato):{items.length && <List/>}— agarlength0 bo'lsa, ekranda "0" chiqib qoladi (0 — falsy, lekin React uni matn sifatida render qiladi); yechim — aniq boolean shart (items.length > 0 && ...) yoki!!. Shuningdekif/forJSX{}ichida ishlamaydi (11.2: 2.5 — ular ifoda emas), shuning uchun har doim ternary/&&/element o'zgaruvchi ishlatasiz. To'g'ri tanlov: ikki variant ternary; bor-yo'q&&; ko'p holat element o'zgaruvchi.
2.13. Ro'yxatlar va key — chuqur (nega kerak, nega index xato)
RO'YXAT — massivni .map() bilan JSX elementlariga aylantirish:
{users.map(user => <li key={user.id}>{user.name}</li>)}
KEY NIMA: React'ga har element uchun BARQAROR, UNIKAL "shaxsiy raqam"
reconciliation (11.2: 2.2) da qaysi element o'zgardi/qo'shildi/o'chdi — aniqlash uchun
NEGA INDEX (key={i}) XATO — ro'yxat O'ZGARSA (qo'shilsa/o'chsa/tartiblansa):
Boshida: [Olma(i=0), Non(i=1), Sut(i=2)]
Olma o'chdi [Non(i=0), Sut(i=1)]
React: "i=0 element matni Olma'dan Non'ga o'zgardi" deb o'ylaydi (NOTO'G'RI!)
state aralashadi (input qiymati boshqa qatorga "sakraydi"), noto'g'ri render, bug
TO'G'RI KEY:
key={user.id} // barqaror unikal id (DB'dan, yoki yaratishda crypto.randomUUID())
key={index} // ro'yxat o'zgarsa — buziladi (faqat STATIK ro'yxatda mayli)
key={Math.random()} // har render'da YANGI React hammasini qayta yaratadi (sekin + state yo'qoladi)
key — JSX prop kabi yozilADI, lekin React ICHIDA ishlatadi (props sifatida kelmaydi)
key faqat .map() (yoki aka-uka ro'yxat)da kerak; bitta elementga kerak emasRo'yxatlar va key — React'ning eng ko'p xato qilinadigan joylaridan biri. Massivni
.map()bilan JSX elementlariga aylantirasiz, va har elementgakeyberasiz.keynima: React'ga har element uchun barqaror, unikal "shaxsiy raqam" — u reconciliation (11.2: 2.2) da qaysi element o'zgargani/qo'shilgani/o'chirilganini aniqlash uchun ishlatiladi. Nega index (key={i}) xato: agar ro'yxat o'zgarsa (element qo'shilsa, o'chsa, tartiblansa), indekslar siljiydi va React "i=0 ning matni o'zgardi" deb noto'g'ri xulosa chiqaradi — natijada komponent state'i aralashadi (input qiymati boshqa qatorga "sakraydi"), noto'g'ri render, qiyin topiladigan buglar. To'g'ri key: barqaror unikal id (key={user.id}— DB'dan kelgan id, yoki element yaratilgandacrypto.randomUUID()bilan generatsiya qilingan). Xatolar:key={index}(faqat statik, o'zgarmaydigan ro'yxatda mayli),key={Math.random()}( — har render'da yangi key React hamma elementni qayta yaratadi sekin + state yo'qoladi).keyJSX prop kabi yoziladi, lekin React uni ichida ishlatadi (komponentga prop sifatida kelmaydi — agar id kerak bo'lsa, alohida prop ber).keyfaqat ro'yxatlarda kerak.
2.14. Lifting state up — state'ni ulashish va qayerda saqlash
MUAMMO: ikki aka-uka komponent BIR XIL ma'lumotni ulashishi kerak
(masalan: qidiruv input va natijalar ro'yxati)
YECHIM: state'ni ENG YAQIN UMUMIY OTAga "ko'tarish" (lift up)
ota state'ni saqlaydi, bolalarga props (qiymat) + callback (o'zgartirish) beradi
App (state: query) state shu yerda (umumiy ota)
/ \
SearchBar ResultList
query={query} results=filtered(query) props (qiymat pastga)
onChange={setQuery} callback (xabar yuqoriga — 11.2: 2.10)
QAYERDA STATE SAQLASH (qoidalar):
- Faqat BITTA komponent ishlatsa o'sha komponentda (colocation — yaqin tut)
- BIR NECHA komponent ulashsa eng yaqin UMUMIY otada (lift up)
- BUTUN ilova ulashsa Context 12.1-bob yoki global store (Redux — 12.2)
"Single source of truth" — har ma'lumot uchun BITTA egasi (nusxalama)
State'ni keraksiz yuqoriga ko'tarma (faqat ulashish kerak bo'lganda — aks holda yaqin tut)Lifting state up (state'ni ko'tarish) — ikki yoki undan ortiq komponent bir xil ma'lumotni ulashishi kerak bo'lganda, state'ni ularning eng yaqin umumiy otasiga ko'taradigan naqsh. Ota state'ni saqlaydi va bolalarga qiymatni props orqali, o'zgartirish funksiyasini callback orqali beradi ("data down, events up" — 11.2: 2.10). Masalan, qidiruv input (
SearchBar) va natijalar (ResultList) birquerystate'ini ulashadiqueryularning otasiApp'da saqlanadi. Qayerda state saqlash (muhim qaror): (1) faqat bitta komponent ishlatsa — o'sha komponentda (colocation — state'ni ishlatadigan joyga yaqin tut); (2) bir necha komponent ulashsa — eng yaqin umumiy otada (lift up); (3) butun ilova ulashsa — Context 12.1-bob yoki global store (Redux/Zustand — 12.2, 12.5). Ikki tamoyil: (1) "single source of truth" — har ma'lumotning bitta egasi bo'lsin (nusxalama, aks holda sinxronlash muammosi qaytadi — 11.1: 2.9); (2) state'ni keraksiz yuqoriga ko'tarma — faqat ulashish zarur bo'lganda (aks holda yaqin tut — ortiqcha re-render va murakkablikdan qoch — 11.11).
2.15. State strukturasini to'g'ri tuzish (tekis, guruhli, dublikatsiz)
YAXSHI STATE STRUKTURASI — kelajakdagi buglarning yarmini oldini oladi
1. HISOBLASH MUMKIN BO'LGANNI STATE'DA SAQLAMA (derived state — 2.14):
const [items] + const [count] // count = items.length'dan kelib chiqadi (dublikat!)
const [items] ... const count = items.length; // render paytida hisobla
2. DUBLIKAT/QARAMA-QARSHI STATE'DAN QOCH (bir haqiqat — ikki joyda emas):
const [items] + const [selectedItem] // selectedItem — items'dagi obyekt NUSXASI
item o'zgarsa, ikkovi rassinxron bo'ladi (qaysi biri to'g'ri?)
const [items] + const [selectedId] // faqat ID saqla obyektni items'dan top
3. BOG'LIQ STATE'LARNI GURUHLA (birga o'zgarsa — bitta obyekt):
~ const [x, setX] + const [y, setY] // kursor pozitsiyasi — doim birga
const [pos, setPos] = useState({ x: 0, y: 0 }); // guruhlangan (birga yangilanadi)
4. CHUQUR ICHMA-ICH EMAS, YASSI (flat) TUT 2.8-bob:
chuqur nested obyekt (yangilash og'riqli)
yassi struktura yoki id bo'yicha "normallashtirilgan" ({ [id]: item })
Qoida: MINIMAL, TEKIS, DUBLIKATSIZ state qolganini HISOBLAState strukturasi — state'ni qanday tashkil qilish kelgusidagi buglarning katta qismini belgilaydi. To'rt tamoyil: (1) hisoblash mumkin bo'lganni state'da saqlamang —
count = items.lengthkabi qiymat state emas, uni render paytida hisoblang (derived state — 2.14, Xato 8; aks holda ikki joyni qo'lda sinxronlash muammosi qaytadi); (2) dublikat va qarama-qarshi state'dan qoching — masalan tanlangan elementning butun nusxasini saqlamang, faqat IDsini saqlang (selectedId) va obyektni ro'yxatdan toping — aks holda element o'zgarganda ikki nusxa rassinxron bo'lib qoladi ("bitta haqiqat" buziladi); (3) birga o'zgaradigan bog'liq state'larni guruhlang — masalan kursorx/ydoim birga yangilansa, ularni bitta obyekt ({ x, y }) qiling; (4) chuqur ichma-ich emas, yassi (flat) tuting 2.8-bob — chuqur joylashtirilgan state'ni immutable yangilash og'riqli, shuning uchun yassi yoki id bo'yicha "normallashtirilgan" ({ [id]: item }) struktura afzal. Umumiy qoida: state minimal, tekis va dublikatsiz bo'lsin — qolgan hamma narsani undan hisoblang. Bu tamoyillar 11.6 (useReducer) va 12-QISM (global state)'da yanada muhimroq bo'ladi.
3. Sintaksis — tez ma'lumotnoma
E'LON 2.2-bob: const [x, setX] = useState(boshlang'ich)
YANGILASH 2.4-bob: setX(yangiQiymat) | setX(prev => prev + 1) // updater 2.6-bob
LAZY INIT: useState(() => qimmatHisob()) // funksiya — faqat 1-render'da
OBYEKT 2.8-bob: setForm({ ...form, name: "Ali" }) | {...form, [e.target.name]: e.target.value}
MASSIV 2.9-bob: setItems([...items, yangi]) | [yangi, ...items]
MASSIV : setItems(items.filter(i => i.id !== id))
MASSIV : setItems(items.map(i => i.id === id ? {...i, ...upd} : i))
HODISA 2.10-bob: onClick={fn} | onClick={() => fn(arg)} | onChange={e => setX(e.target.value)}
INPUT 2.11-bob: <input value={x} onChange={e => setX(e.target.value)} /> // controlled
CHECKBOX: <input type="checkbox" checked={x} onChange={e => setX(e.target.checked)} />
UNCONTROLLED: <input ref={inputRef} defaultValue="..." /> // qiymat: inputRef.current.value (2.11a)
SHART 2.12-bob: {cond ? <A/> : <B/>} | {cond && <A/>} | if(!x) return null
RO'YXAT 2.13-bob: {arr.map(x => <li key={x.id}>{x.name}</li>)} // unikal key4. Batafsil kod namunalari
Misol 1 — Eng oddiy state: hisoblagich (2.1, 2.2, 2.4)
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0); // state e'lon (boshlang'ich 0)
return (
<div>
<p>Hisob: {count}</p> {/* state'ni ko'rsatamiz */}
<button onClick={() => setCount(count + 1)}>+1</button> {/* state'ni oshiramiz */}
<button onClick={() => setCount(count - 1)}>-1</button>
<button onClick={() => setCount(0)}>Reset</button>
</div>
);
}
// setCount re-render yangi count ekran yangilanadi (UI = f(state)). render() YO'Q!Misol 2 — Lazy initial state (qimmat boshlang'ich hisob)
function App() {
// Har render'da ishlaydi (lekin natija faqat 1-marta kerak — isrof):
// const [data] = useState(qimmatHisob());
// FUNKSIYA bersang — React uni FAQAT birinchi render'da chaqiradi (lazy):
const [data, setData] = useState(() => {
const saved = localStorage.getItem("data"); // qimmat: localStorage o'qish
return saved ? JSON.parse(saved) : []; // faqat 1-render'da bajariladi
});
return <div>{data.length} ta element</div>;
}
// useState(qiymat) — qiymat har render'da hisoblanadi; useState(() => qiymat) — faqat 1-martaMisol 3 — Snapshot tuzog'i: nega 3 emas, 1? (2.3)
function Counter() {
const [count, setCount] = useState(0);
function handleTriple() {
setCount(count + 1); // count = 0 setCount(1)
setCount(count + 1); // count HALI 0 (snapshot) setCount(1)
setCount(count + 1); // count HALI 0 setCount(1)
// Natija: 1 (3 emas!) — count bu render davomida 0 bo'lib QOTGAN (2.3)
}
return <button onClick={handleTriple}>{count} — uchta +1</button>;
}
// Bu — "nega yangilanmayapti" tuzog'ining ildizi. Yechim — Misol 4 (updater)Misol 4 — Updater funksiya: to'g'ri ketma-ket yangilash (2.6)
function Counter() {
const [count, setCount] = useState(0);
function handleTriple() {
setCount(prev => prev + 1); // prev = 0 1
setCount(prev => prev + 1); // prev = 1 2 (React navbatda beradi)
setCount(prev => prev + 1); // prev = 2 3 Natija: 3
}
// Asinxron holatda ham updater shart (snapshot eskiradi):
function handleDelayed() {
setTimeout(() => setCount(prev => prev + 1), 1000); // 1s keyin — prev har doim yangi
}
return (
<>
<button onClick={handleTriple}>{count} — +3</button>
<button onClick={handleDelayed}>Kechikkan +1</button>
</>
);
}Misol 5 — Obyekt state: forma (spread — 2.8)
function ProfileForm() {
const [form, setForm] = useState({ name: "", email: "", age: 0 });
// Bitta universal handler — barcha maydonlar uchun (dinamik maydon nomi — 2.11)
function handleChange(e) {
const { name, value } = e.target;
setForm(prev => ({ ...prev, [name]: value })); // [name] — computed property (qaysi maydon?)
}
return (
<form>
<input name="name" value={form.name} onChange={handleChange} placeholder="Ism" />
<input name="email" value={form.email} onChange={handleChange} placeholder="Email" />
<input name="age" type="number" value={form.age} onChange={handleChange} />
<pre>{JSON.stringify(form, null, 2)}</pre> {/* state'ni jonli ko'rsatamiz */}
</form>
);
}
// Bitta handleChange — barcha inputlarni boshqaradi (name atributi orqali ajratiladi)Misol 6 — Ichma-ich obyekt state (nested — 2.8)
function Settings() {
const [user, setUser] = useState({
name: "Ali",
address: { city: "Toshkent", street: "Navoiy" }, // ichma-ich obyekt
});
function updateCity(city) {
setUser(prev => ({
...prev, // tashqi qatlam nusxasi
address: { ...prev.address, city }, // ichki qatlam HAM nusxalanadi (street saqlanadi)
}));
}
// { ...prev, address: { city } } bo'lsa — street YO'QOLADI! (2.8)
return (
<div>
<p>{user.name} — {user.address.city}, {user.address.street}</p>
<button onClick={() => updateCity("Samarqand")}>Shaharni o'zgartir</button>
</div>
);
}Misol 7 — Massiv state: qo'shish va o'chirish (2.9)
function TodoList() {
const [todos, setTodos] = useState([
{ id: 1, text: "React o'rganish" },
{ id: 2, text: "Loyiha qilish" },
]);
const [input, setInput] = useState("");
function addTodo() {
if (!input.trim()) return; // bo'sh bo'lmasin
const newTodo = { id: crypto.randomUUID(), text: input }; // unikal id (2.13)
setTodos([...todos, newTodo]); // oxiriga (push o'rniga — 2.9)
setInput(""); // inputni tozala
}
function removeTodo(id) {
setTodos(todos.filter(t => t.id !== id)); // id bo'yicha o'chir (filter — 2.9)
}
return (
<div>
<input value={input} onChange={e => setInput(e.target.value)} />
<button onClick={addTodo}>Qo'shish</button>
<ul>
{todos.map(todo => ( // ro'yxat (2.13)
<li key={todo.id}> {/* unikal key (id) */}
{todo.text}
<button onClick={() => removeTodo(todo.id)}></button> {/* argument uzatish — 2.10 */}
</li>
))}
</ul>
</div>
);
}Misol 8 — Massiv state: elementni yangilash (toggle — 2.9)
function TaskList() {
const [tasks, setTasks] = useState([
{ id: 1, text: "Sport", done: false },
{ id: 2, text: "O'qish", done: true },
]);
function toggleDone(id) {
setTasks(tasks.map(task => // map — bitta elementni almashtirish
task.id === id
? { ...task, done: !task.done } // mosini: done'ni teskari qil (yangi obyekt)
: task // qolganini o'z holida (o'zgartirmaymiz)
));
}
return (
<ul>
{tasks.map(task => (
<li key={task.id} style={{ textDecoration: task.done ? "line-through" : "none" }}>
<input type="checkbox" checked={task.done} onChange={() => toggleDone(task.id)} />
{task.text}
</li>
))}
</ul>
);
}
// map ichida mos kelmaganlarni O'ZGARTIRMASDAN qaytaramiz (faqat keraklisini yangilaymiz)Misol 9 — Controlled inputs: barcha turlar (2.11)
function RegistrationForm() {
const [name, setName] = useState(""); // text
const [agree, setAgree] = useState(false); // checkbox
const [role, setRole] = useState("user"); // select
const [age, setAge] = useState(18); // number
return (
<form>
{/* text */}
<input value={name} onChange={e => setName(e.target.value)} placeholder="Ism" />
{/* checkbox — checked + e.target.checked (boolean) */}
<label>
<input type="checkbox" checked={agree} onChange={e => setAgree(e.target.checked)} />
Shartlarga roziman
</label>
{/* select — value + e.target.value */}
<select value={role} onChange={e => setRole(e.target.value)}>
<option value="user">Foydalanuvchi</option>
<option value="admin">Admin</option>
</select>
{/* number — Number() bilan o'girish */}
<input type="number" value={age} onChange={e => setAge(Number(e.target.value))} />
{/* tugma faqat rozi bo'lsa faol (shartli o'chirish — controlled kuchi) */}
<button disabled={!agree}>Ro'yxatdan o'tish</button>
</form>
);
}Misol 10 — Forma submit va preventDefault (2.10, 2.11)
function LoginForm() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
function handleSubmit(e) {
e.preventDefault(); // sahifa qayta yuklanishini to'xtat (11.1: 2.6)
if (!email.includes("@")) {
setError("Email noto'g'ri"); // shartli xato (2.12 da ko'rsatamiz)
return;
}
setError("");
console.log("Kirish:", { email, password }); // bu yerda API chaqiruvi (12.4)
}
return (
<form onSubmit={handleSubmit}> {/* onSubmit — formaga, tugmaga emas */}
<input value={email} onChange={e => setEmail(e.target.value)} placeholder="Email" />
<input type="password" value={password} onChange={e => setPassword(e.target.value)} />
{error && <p className="error">{error}</p>} {/* shartli render (&&) — 2.12 */}
<button type="submit">Kirish</button>
</form>
);
}Misol 11 — Shartli render: barcha usullar (2.12)
function DataView({ loading, error, data }) {
// 1. Element o'zgaruvchi (ko'p holat — eng toza)
let content;
if (loading) content = <Spinner />;
else if (error) content = <p className="error">Xato: {error}</p>;
else if (data.length === 0) content = <p>Ma'lumot yo'q</p>;
else content = <ul>{data.map(d => <li key={d.id}>{d.name}</li>)}</ul>;
return (
<div>
{content} {/* 1. o'zgaruvchi */}
{/* 2. ternary (ikki variant) */}
{loading ? <small>Yuklanmoqda...</small> : <small>Tayyor</small>}
{/* 3. && (bor-yo'q) — TO'G'RI boolean shart (length > 0, raqam 0 tuzog'i — 2.12) */}
{data.length > 0 && <p>Jami: {data.length} ta</p>}
{/* {data.length && ...} bo'lsa — 0 da ekranda "0" chiqardi 2.12-bob */}
</div>
);
}Misol 12 — Lifting state up: aka-uka ulashishi (2.14)
// Bola 1 — qidiruv input (state'ni o'zi saqlamaydi, otadan oladi)
function SearchBar({ query, onQueryChange }) {
return (
<input value={query} onChange={e => onQueryChange(e.target.value)} placeholder="Qidirish..." />
);
}
// Bola 2 — natijalar (otadan filtrlangan ma'lumot oladi)
function ResultList({ results }) {
return <ul>{results.map(r => <li key={r.id}>{r.name}</li>)}</ul>;
}
// Ota — state SHU YERDA (umumiy ota), ikki bolaga ulashadi
function SearchPage({ products }) {
const [query, setQuery] = useState(""); // state ko'tarildi (lifted up)
const filtered = products.filter(p => // query bo'yicha filtr (render paytida hisob)
p.name.toLowerCase().includes(query.toLowerCase())
);
return (
<div>
<SearchBar query={query} onQueryChange={setQuery} /> {/* qiymat + callback pastga */}
<ResultList results={filtered} /> {/* hisoblangan natija pastga */}
</div>
);
}
// query — BITTA egasi (SearchPage); ikki bola uni ulashadi (single source of truth — 2.14)Misol 13 — Toggle va boolean state (modal, accordion)
function Accordion({ title, children }) {
const [isOpen, setIsOpen] = useState(false);
return (
<div className="accordion">
<button onClick={() => setIsOpen(prev => !prev)}> {/* toggle — updater 2.6-bob */}
{title} {isOpen ? "▲" : "▼"} {/* ternary belgi 2.12-bob */}
</button>
{isOpen && <div className="content">{children}</div>} {/* && — ochiq bo'lsa ko'rsat 2.12-bob */}
</div>
);
}
// setIsOpen(prev => !prev) — eskiga bog'liq updater 2.6-bob; ikki marta bossang to'g'ri ishlaydiMisol 14 — Ro'yxat filtri va saralash (state + hisoblangan qiymat)
function ProductBoard({ products }) {
const [search, setSearch] = useState("");
const [sortBy, setSortBy] = useState("name"); // "name" yoki "price"
// Hisoblangan qiymat — state'da SAQLAMAYMIZ (render paytida hosil — single source)
const visible = products
.filter(p => p.name.toLowerCase().includes(search.toLowerCase())) // filtr
.sort((a, b) => // saralash (yangi massivda — filter nusxa bergan)
sortBy === "price" ? a.price - b.price : a.name.localeCompare(b.name)
);
return (
<div>
<input value={search} onChange={e => setSearch(e.target.value)} placeholder="Qidirish" />
<select value={sortBy} onChange={e => setSortBy(e.target.value)}>
<option value="name">Nom bo'yicha</option>
<option value="price">Narx bo'yicha</option>
</select>
{visible.length > 0 ? ( // shartli render (ternary — 2.12)
<ul>{visible.map(p => <li key={p.id}>{p.name} — {p.price}</li>)}</ul>
) : (
<p>Hech narsa topilmadi</p>
)}
</div>
);
}
// "visible" — state EMAS (search/sortBy'dan KELIB CHIQADI). Hosilani state'da saqlama 11.5-bob!Misol 15 — Hammasini birlashtirgan mini-ilova: "Vazifalar"
function TaskApp() {
const [tasks, setTasks] = useState([]); // ro'yxat (massiv state)
const [input, setInput] = useState(""); // input (controlled)
const [filter, setFilter] = useState("all"); // filtr: all/active/done
function addTask() {
if (!input.trim()) return;
setTasks(prev => [...prev, { id: crypto.randomUUID(), text: input, done: false }]); // updater
setInput("");
}
const toggle = id => setTasks(prev => prev.map(t => t.id === id ? { ...t, done: !t.done } : t)); //
const remove = id => setTasks(prev => prev.filter(t => t.id !== id)); //
// Hisoblangan: filtrlangan ro'yxat (state EMAS — tasks/filter'dan)
const visible = tasks.filter(t =>
filter === "all" ? true : filter === "done" ? t.done : !t.done
);
return (
<div>
<input value={input} onChange={e => setInput(e.target.value)}
onKeyDown={e => e.key === "Enter" && addTask()} /> {/* Enter bilan ham — 2.10 */}
<button onClick={addTask}>Qo'shish</button>
<div>
{["all", "active", "done"].map(f => ( // filtr tugmalari (ro'yxat — key)
<button key={f} onClick={() => setFilter(f)}
style={{ fontWeight: filter === f ? "bold" : "normal" }}>{f}</button>
))}
</div>
{visible.length === 0 && <p>Vazifa yo'q</p>} {/* shartli (&&) — 2.12 */}
<ul>
{visible.map(task => ( // ro'yxat (key — 2.13)
<li key={task.id}>
<input type="checkbox" checked={task.done} onChange={() => toggle(task.id)} />
<span style={{ textDecoration: task.done ? "line-through" : "none" }}>{task.text}</span>
<button onClick={() => remove(task.id)}></button>
</li>
))}
</ul>
<p>Jami: {tasks.length} | Bajarilgan: {tasks.filter(t => t.done).length}</p>
</div>
);
}
// 11.1: 2.9 dagi QO'LDA render() butunlay YO'Q — faqat state'ni o'zgartiramiz, React qoladi (UI=f(state))5. To'g'ri va noto'g'ri holatlar
1) Oddiy o'zgaruvchi vs state
let count = 0; count++ (re-render yo'q, render'da tiklanadi — 2.1)
const [count, setCount] = useState(0); setCount(count + 1)2) Ketma-ket yangilash
setCount(count+1); setCount(count+1) (snapshot — natija +1 — 2.3)
setCount(p => p+1); setCount(p => p+1) (updater — natija +2 — 2.6)3) Obyekt/massivni yangilash
user.age = 26; setUser(user) / items.push(x); setItems(items) (mutatsiya — re-render yo'q — 2.7)
setUser({...user, age:26}) / setItems([...items, x]) (yangi nusxa)4) Hodisa ulash
onClick={handleClick()} (darrov chaqiriladi — render'da — 2.10)
onClick={handleClick} yoki onClick={() => handleClick(id)}5) Controlled input
<input value={name} /> (onChange yo'q — read-only, yozib bo'lmaydi — 2.11)
<input value={name} onChange={e => setName(e.target.value)} />6) && tuzog'i (raqam 0)
{items.length && <List/>} (0 da ekranda "0" — 2.12)
{items.length > 0 && <List/>} (aniq boolean)7) Ro'yxat key
key={index} yoki key={Math.random()} (ro'yxat o'zgarsa buziladi — 2.13)
key={item.id} (barqaror unikal id)8) Hosilangan qiymatni state'da saqlash
const [filtered, setFiltered] = useState([]); ... (search o'zgarsa qo'lda sinxronlash — 11.1: 2.9 qaytadi)
const filtered = items.filter(...) (render paytida hisobla — Misol 14)6. Keng tarqalgan xatolar va yechimlari
Xato 1 — "State o'zgaryapti, lekin ekran yangilanmayapti"
Sababi: obyekt/massivni mutatsiya qildingiz (havola bir xil React ko'rmaydi — 2.7). Yechimi: yangi nusxa yarat ({...obj}, [...arr], map/filter — 2.8, 2.9).
Xato 2 — "setX'dan keyin darrov o'qidim, eski qiymat chiqdi"
Sababi: state yangilanishi asinxron (keyingi render'da kuchga kiradi — 2.5). Yechimi: yangi qiymatni alohida o'zgaruvchiga ol (const next = ...; setX(next); use(next)), yoki effektni useEffect bilan kuzat 11.5-bob.
Xato 3 — Too many re-renders. React limits the number of renders
Sababi: render paytida setX chaqirdingiz (onClick={setX(1)} — chaqiruv, yoki to'g'ridan return'da). Bu cheksiz tsikl: render setX render setX... Yechimi: onClick={() => setX(1)} (funksiya bilan o'ra — 2.10).
Xato 4 — A component is changing an uncontrolled input to be controlled
Sababi: valueni undefined bilan boshladingiz, keyin qiymat berdingiz. Yechimi: boshlang'ich qiymat ber (useState(""), useState(0) — 2.2, 2.11).
Xato 5 — Ro'yxatda input qiymati noto'g'ri qatorga "sakraydi"
Sababi: key={index} ishlatdingiz, ro'yxat o'zgardi 2.13-bob. Yechimi: barqaror unikal key={item.id}.
Xato 6 — Cannot update a component while rendering a different component
Sababi: bir komponent render paytida boshqasining state'ini o'zgartirmoqda. Yechimi: state o'zgarishini hodisa ichida yoki useEffectda bajar 11.5-bob, render paytida emas.
Xato 7 — Ekranda kutilmagan "0" yoki "false" chiqadi
Sababi: && chap tomonida raqam (0) yoki noto'g'ri qiymat 2.12-bob. Yechimi: aniq boolean shart (length > 0, Boolean(x), !!x).
7. Integratsiya — bu mavzu stack'ning qayerida uchraydi
- DOM og'rig'i (11.1: 2.9): state + re-render qo'lda
render()ni butunlay yo'qotadi. - Komponent/props 11.2-bob: props o'zgarmas; o'zgaruvchi ma'lumot — state; callback 2.10-bob bilan bola otaga.
- Hooks 11.5-bob:
useState— birinchi hook;useEffect— state o'zgarishiga reaksiya. - useReducer 11.6-bob: murakkab state mantiqi (ko'p bog'liq state).
- Forma 11.10-bob: controlled inputs — React Hook Form buni soddalashtiradi;
useRefesa uncontrolled input asosi (2.11a, 11.5). - Performance 11.11-bob: keraksiz re-render;
memo/useMemoimmutability'ga tayanadi 2.7-bob. - State boshqaruvi (12-QISM): Context/Redux — lifting state up 2.14-bob kengaytmasi.
- Data fetching 12.4-bob: server ma'lumoti ham state (loading/error/data — 2.12).
8. Eng yaxshi amaliyotlar (best practices)
- Hosilangan qiymatni state'da saqlama (filtr, hisob — render paytida hisobla — Misol 14, Xato 8).
- Immutability (obyekt/massivni hech qachon mutatsiya qilma — yangi nusxa — 2.7, 2.8, 2.9).
- Updater funksiya (oldingi qiymatga bog'liq bo'lsa
prev =>— 2.6). - State'ni yaqin tut (faqat kerakli komponentda; ulashish kerak bo'lganda lift up — 2.14).
- Single source of truth (har ma'lumotning bitta egasi — nusxalama — 2.14).
- Controlled inputs (
value+onChange— forma ustidan to'liq nazorat — 2.11). - Barqaror unikal
key(id — index/random emas — 2.13). &&da aniq boolean (raqam 0 tuzog'idan qoch — 2.12).- Handler'ni o'ra (
() => fn(arg)— render'da chaqirma — 2.10). - State'ni minimal tut (faqat kerakli ma'lumot; qolganini hisobla — kam state, kam bug).
- State strukturasi (tekis, guruhli, dublikatsiz — obyekt nusxasi emas, ID saqla — 2.15).
- Controlled'ni afzal ko'r (uncontrolled/ref — faqat oddiy holat yoki fayl input — 2.11a).
9. Amaliy loyiha: "Interaktiv Xaridlar Ro'yxati (Shopping List)"
11.1-bobda xuddi shu g'oyani vanilla DOM bilan amalga oshirdik (og'riq bilan). Endi uni React state bilan qayta yozamiz — va farqni yaqqol his qilamiz.
Maqsad
To'liq interaktiv xaridlar ro'yxati: mahsulot qo'shish, sonini o'zgartirish, "olindi" belgilash, o'chirish, filtrlash, umumiy hisob — barchasi state bilan.
Talablar (requirements)
- Qo'shish: input (controlled — 2.11) + tugma; bo'sh qo'shilmasin; Enter bilan ham ishlasin (Misol 15).
- Massiv state: har element
{id, name, qty, bought}— unikal id (crypto.randomUUID()— 2.13). - Son boshqaruvi:
+/−tugmalari (mapbilan yangilash — 2.9, Misol 8); son 1 dan kam bo'lmasin. - "Olindi" toggle: checkbox bilan
boughtni almashtir (updater — 2.6, Misol 13). - O'chirish:
filterbilan (2.9, Misol 7). - Filtr: "Hammasi / Olinmagan / Olingan" — hisoblangan ro'yxat (state EMAS — Misol 14).
- Shartli render: ro'yxat bo'sh bo'lsa "Ro'yxat bo'sh", filtr natijasi 0 bo'lsa boshqa xabar 2.12-bob.
- Statistika: "Jami N ta, olingan M ta" — hisoblangan (render paytida — 2.14).
- Immutability: hech qayerda mutatsiya yo'q (push/splice/joyida o'zgartirish — taqiq — 2.7).
- Tahrirlash (bonus): mavjud mahsulot nomini ikki marta bosib tahrirlash (inline edit — qo'shimcha state).
Maslahatlar (hint)
- State'ni minimal tut:
items,input,filter— yetadi. Filtrlangan ro'yxat va statistika — hisoblangan (state emas — 2.14, Xato 8). - Massivni o'zgartirganda har doim
map/filter/[...](push/splice yo'q — 2.9). - Oldingi qiymatga bog'liq har yangilashda updater (
prev =>— 2.6). key—item.id(index emas — 2.13).- 11.1-bobdagi vanilla versiyangiz bilan solishtiring:
render()ni necha marta yozgan edingiz? Bu yerda nol marta (React o'zi qiladi). Mana farq.
"Tayyor" mezonlari (acceptance criteria)
- Qo'shish/o'chirish ishlaydi (controlled input, filter).
- Son
+/−(map bilan, immutable). - "Olindi" toggle (checkbox, updater).
- Filtr (hammasi/olingan/olinmagan) — hisoblangan ro'yxat.
- Shartli render (bo'sh holatlar).
- Statistika hisoblangan (state'da saqlanmaydi).
- Hech qanday mutatsiya yo'q (faqat yangi nusxalar).
- Barcha
key— unikal id. - UI hech qachon ma'lumotga zid kelmaydi (avtomatik sinxron).
Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.
10. Xulosa va keyingi bobga ko'prik
Bu bobda React'ning yuragi — state — ni chuqur o'rgandik:
- State (komponent xotirasi, nega oddiy o'zgaruvchi yetmaydi — 2.1);
useStateanatomiyasi 2.2-bob; state — snapshot (har render o'z qiymati — 2.3); yangilash re-render (UI = f(state)— 2.4). - Asinxron/batched yangilanish 2.5-bob; updater funksiya (
prev =>— 2.6); immutability (yangi nusxa — 2.7); obyekt 2.8-bob va massiv 2.9-bob ni to'g'ri yangilash. - Hodisalar (handler, argument, synthetic — 2.10); controlled inputs 2.11-bob va uncontrolled/ref farqi (2.11a); shartli render (ternary/
&&/o'zgaruvchi + tuzoqlar — 2.12); ro'yxat va key 2.13-bob; lifting state up 2.14-bob; state strukturasi (tekis, dublikatsiz — 2.15).
Endi siz interaktiv UI qura olasiz — tugma, forma, ro'yxat, filtr — va eng muhimi, 11.1-bobdagi butun og'riq (qo'lda render(), sinxronlash) butunlay yo'qoldi. UI = f(state) endi siz uchun jonli haqiqat.
Keyingi bob — 11.5-bob: Hooks — useState, useEffect, useContext, useRef. State'ni o'rgandik; endi hooklar dunyosiga to'liq kiramiz. Rules of Hooks (nega yuqorida, nega shartsiz), useEffect (komponentni tashqi dunyo bilan bog'lash — API chaqiruvi, taymer, obuna — va cleanup), useContext (props drilling'siz ma'lumot ulashish), useRef (DOM elementga to'g'ridan kirish va render'siz qiymat saqlash). Bu hooklar — har real React ilovasining nafasi.
Foydalanilgan rasmiy/ishonchli manbalar
- React rasmiy hujjati (react.dev) — "State: A Component's Memory", "Render and Commit", "State as a Snapshot", "Queueing a Series of State Updates", "Updating Objects in State", "Updating Arrays in State"
- react.dev — "Responding to Events", "Conditional Rendering", "Rendering Lists", "Sharing State Between Components", "Choosing the State Structure", "Preserving and Resetting State"
- react.dev —
useStatevauseRefAPI reference; "Keeping Components Pure"; "React and the DOM: Controlled vs Uncontrolled Components" - MDN Web Docs — Array metodlari (
map,filter,sort), spread sintaksisi (...), computed property nomlari,crypto.randomUUID()
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!