11.5-bob: Hooks — useState, useEffect, useContext, useRef
11-QISM — Frontend: React · 5-mavzu
1. Kirish va motivatsiya
11.4-bobda useState bilan birinchi hook'ni ishlatdik va ilovamizga "xotira" berdik. Lekin useState — bu butun bir oilaning faqat bitta a'zosi. Hooklar — bu React'ning eng katta inqilobi (2018-yil, 16.8 versiya): ular funksiya komponentlarni o'zgartirib, ularga shu paytgacha faqat class komponentlarda mavjud bo'lgan barcha imkoniyatlarni (state, hayot sikli, kontekst) berdi — va buni ancha sodda, qayta ishlatiladigan tarzda qildi. Bugun hech kim yangi React kodini class bilan yozmaydi; butun zamonaviy React — funksiya + hooklar ustiga qurilgan.
Bu bobda biz to'rtta eng muhim hookni chuqur o'rganamiz. useState (xotira — 11.4'da o'rgandik, qisqa takror) — komponent state'i. useEffect — komponentni tashqi dunyo bilan bog'lash (API chaqiruvi, taymer, obuna, DOM bilan ishlash) — bu eng kuchli, lekin eng ko'p noto'g'ri ishlatiladigan hook. useContext — ma'lumotni props drillingsiz (har qatlamdan qo'lda uzatmasdan) butun daraxt bo'ylab ulashish (mavzu, til, autentifikatsiya). useRef — DOM elementiga to'g'ridan kirish va re-render'siz qiymat saqlash. Va eng muhimi — barcha hooklar bo'ysunadigan ikkita qoida: Rules of Hooks — ularni nega shunday yozish kerakligini chuqur tushunamiz (bu yodlash emas, React'ning ichki mexanizmidan kelib chiqadigan zaruriyat).
Bu bob: hook nima va nega (class'dan hooklarga o'tish tarixi), Rules of Hooks (nega funksiya tepasida, nega shart/tsikl ichida emas — React hooklarni chaqiruv tartibi bilan kuzatishi), useEffect (side effect nima, dependency array, cleanup, "sinxronlash" mental modeli, eng keng tuzoqlar — missing deps, infinite loop, stale closure), qachon useEffect KERAK EMAS (react.dev'ning muhim ogohlantirishi — derived state, event handlerda effect ishlatmaslik), useContext (props drilling Provider/Consumer), useRef (DOM kirish va render'siz mutable qiymat). Bundan tashqari, amaliyotda hal qiluvchi — stale closure, "You Might Not Need an Effect", useRef vs useState farqi — ham qamraladi.
O'xshatish: Hooklar — komponentning organlari va sezgi a'zolari.
useState— xotira (komponent nimani esda saqlaydi).useEffect— komponentning tashqi dunyo bilan aloqasi: ko'zlari (serverdan ma'lumot oladi), quloqlari (hodisalarni tinglaydi), qo'llari (taymer o'rnatadi, DOM'ga tegadi) — va eng muhimi, tartib-intizomi: ish tugagach orqasini yig'ishtiradi (cleanup — taymerni o'chiradi, obunani bekor qiladi).useContext— umumiy radio to'lqini: butun ilova bir kanalga ulanib, markazdan kelgan ma'lumotni (mavzu, til) eshitadi — har biriga alohida sim tortish (props drilling) shart emas.useRef— komponentning cho'ntak daftarchasi: unga yozasiz, lekin yozganingiz hech kimga ko'rinmaydi va sizni "qayta tug'ilishga" (re-render) majburlamaydi — DOM elementiga ishora yoki esda tutiladigan, lekin ekranga chiqmaydigan qiymat uchun.
Nega muhim?
- Real ilova nafasi — har React loyihada API chaqiruvi (
useEffect), global ma'lumot (useContext), DOM kirish (useRef) bor. - Eng ko'p xato
useEffectda — stale closure, infinite loop, missing deps — junior'ning eng katta tuzoqlari shu yerda. - "Effect kerak emas" bilimi — keraksiz effect — sekin va xato kod; buni bilmaslik — senior'dan junior'ni ajratadi.
- Custom hooklar poydevori — 11.7'da o'z hooklaringizni yozasiz; avval bularni puxta bilish kerak.
2. Nazariya — chuqur tushuntirish
2.1. Hook nima va nega (class hooklar)
HOOK — funksiya komponentga React imkoniyatlarini "ulaydigan" maxsus funksiya
(nomi "use" bilan boshlanadi: useState, useEffect, useRef, useContext...)
TARIX (nega hooklar paydo bo'ldi):
ESKI (class komponent — murakkab):
class Counter extends React.Component {
constructor() { super(); this.state = { count: 0 }; }
componentDidMount() { /* mount */ }
componentDidUpdate() { /* update */ }
componentWillUnmount() { /* cleanup */ }
render() { return <button onClick={() => this.setState(...)}>...</button>; }
}
MUAMMOLAR: this chalkash, mantiq 3 metodga bo'linib ketadi, qayta ishlatish qiyin (HOC do'zaxi)
YANGI (funksiya + hook — sodda):
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => { /* mount + update + cleanup — BIR joyda */ });
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
Hooklar (2018, React 16.8): this yo'q, mantiq birga, qayta ishlatish oson (custom hook — 11.7)Hook — funksiya komponentga React imkoniyatlarini (state, hayot sikli, kontekst) "ulaydigan" maxsus funksiya; nomi har doim
usebilan boshlanadi (useState,useEffect,useRef,useContext). Hooklar nega paydo bo'ldi: eski React'da state va hayot sikli faqat class komponentlarda mavjud edi (this.state,componentDidMount,componentWillUnmount), va bu uch muammoni keltirardi: (1)thischalkashligi (bog'lash, kontekst); (2) bog'liq mantiq uch xil metodga bo'linib ketardi (masalan obunani ochishcomponentDidMountda, yopishcomponentWillUnmountda — ajralgan); (3) mantiqni komponentlar orasida qayta ishlatish qiyin edi (HOC/render props "do'zaxi" — 11.13). Hooklar (2018, React 16.8) bularning hammasini hal qildi:thisyo'q, bog'liq mantiq bir joyda (useEffectichida ochish va cleanup birga), va mantiqni custom hook sifatida osongina qayta ishlatish 11.7-bob. Bugun zamonaviy React butunlay funksiya + hook ustiga quriladi; class komponentlar eski kodda qoladi, lekin yangi kod yozmaysiz.
2.2. Rules of Hooks — nega tepada, nega shartsiz (chuqur)
IKKI QOIDA (qat'iy):
1. Hooklarni faqat ENG YUQORIDA chaqir (shart, tsikl, ichki funksiya ICHIDA EMAS)
2. Hooklarni faqat React funksiyalarida chaqir (komponent yoki custom hook — 11.7)
NEGA? React hooklarni NOM bilan emas, CHAQIRUV TARTIBI bilan kuzatadi:
function Form() {
const [name, setName] = useState(""); // hook #1
const [age, setAge] = useState(0); // hook #2
useEffect(() => {...}); // hook #3
// React ichida: [#1: name, #2: age, #3: effect] — TARTIB bo'yicha massiv
}
SHART ICHIDA — tartib BUZILADI:
if (loggedIn) {
const [name, setName] = useState(""); // ba'zan #1, ba'zan YO'Q!
} // React tartibni yo'qotadi state aralashadi
┌────────────────────────────────────────────────────────────┐
│ Render 1 (loggedIn=true): [#1 name, #2 age] │
│ Render 2 (loggedIn=false): [#1 age] name o'tib ketdi! │
│ React #1 ni "name" deb bilardi, endi "age" FALOKAT │
└────────────────────────────────────────────────────────────┘
Hooklar HAR render'da BIR XIL TARTIB, BIR XIL SONDA chaqirilishi SHART
ESLint plugin (eslint-plugin-react-hooks) buni avtomatik tekshiradi (15.3)Rules of Hooks — ikkita qat'iy qoida: (1) hooklarni faqat komponentning eng yuqorisida chaqir — shart, tsikl, ichki funksiya ichida emas; (2) hooklarni faqat React funksiyalarida (komponent yoki custom hook) chaqir. Nega bu qoidalar? Chunki React hooklarni ularning nomi bilan emas, chaqiruv tartibi bilan kuzatadi: har render'da hooklar ketma-ket chaqiriladi va React ularni ichki massivda tartib raqami bo'yicha saqlaydi (
[#1, #2, #3]). Agar hookni shart ichida qo'ysangiz, ba'zan u chaqiriladi, ba'zan yo'q — tartib siljiydi va React#1ni bir render'da "name", boshqasida "age" deb biladi state aralashadi, kutilmagan xatolar. Demak hooklar har render'da bir xil tartibda, bir xil sonda chaqirilishi shart. Shart kerak bo'lsa — uni hook ichida qo'yish kerak (useEffect(() => { if (x) {...} })), hookni shart ichida emas. Bu qoidanieslint-plugin-react-hooksavtomatik tekshiradi (har React loyihada yoqilgan bo'lsin — 15.3) — u xatolarni yozish paytining o'zida tutadi.
2.3. useState — ko'p state va boshqaruv (qisqa takror)
KOMPONENTDA ISTAGANCHA state bo'lishi mumkin (har biri mustaqil):
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [loading, setLoading] = useState(false);
ALOHIDA state vs BITTA obyekt state — qaysi biri?
Alohida (oddiy, mustaqil maydonlar): const [a]=.. const [b]=..
Obyekt (birga o'zgaradigan, forma): const [form, setForm] = useState({a, b})
ikkalasi to'g'ri; bog'liqligi va soni bo'yicha tanlanadi (juda ko'p bo'lsa — useReducer 11.6)
Bir-biriga bog'liq state'larni alohida tutsang — sinxronlash muammosi (useReducer afzal)
Mustaqil, oddiy state'lar — alohida toza (form butun bo'lsa — obyekt)
useState— ko'p state — komponentda istalgancha state bo'lishi mumkin, har biri mustaqil (name,loading). Savol: alohida state'lar (const [a],const [b]) yoki bitta obyekt state (useState({a, b}))? Ikkalasi ham to'g'ri, tanlov bog'liqlikga qarab: mustaqil, oddiy maydonlar — alohida (toza, har biri o'zicha); birga o'zgaradigan, mantiqan bog'liq maydonlar (forma) — bitta obyekt (11.4: 2.8). Agar state'lar bir-biriga kuchli bog'liq bo'lsa va birga yangilansa, ularni alohida tutish sinxronlash muammosini keltirishi mumkin — bundauseReducer11.6-bob afzal (bir nechta bog'liq state'ni bitta mantiqda boshqaradi). Hozircha qoida: oddiy mustaqil qiymat —useState; murakkab bog'liq mantiq —useReducer(11.6'da o'rganamiz). Bu bobda asosiy e'tibor —useEffect,useContext,useRef.
2.3a. useState — lazy init va funksional update (chuqur)
LAZY INIT (dangasa boshlang'ich qiymat) — boshlang'ich qiymat QIMMAT bo'lganda:
const [state, set] = useState(qimmatHisob()); // qimmatHisob() HAR render'da chaqiriladi!
const [state, set] = useState(() => qimmatHisob()); // funksiya — FAQAT birinchi render'da
useState argumenti FUNKSIYA bo'lsa, React uni faqat mount'da bir marta chaqiradi
(masalan localStorage'dan o'qish, katta massiv qurish — har render'da takrorlanmasin)
FUNKSIONAL UPDATE (updater funksiya) — yangi qiymat ESKISIGA bog'liq bo'lganda:
setCount(count + 1); setCount(count + 1); // ikkalasi ham BIR xil snapshot count'dan +1
setCount(c => c + 1); setCount(c => c + 1); // React navbatga qo'yadi +2 (11.4: 2.6)
┌────────────────────────────────────────────────────────────────┐
│ set(yangiQiymat) — to'g'ridan qiymat (eskiga bog'liq emas) │
│ set(esk => yangi) — updater; esk = navbatdagi eng yangi qiymat │
└────────────────────────────────────────────────────────────────┘
Lazy init: argument funksiya (chaqiruv EMAS) — useState(fn), useState(fn()) EMAS
Updater: asinxron/taymer/ketma-ket setX'da stale closure'dan himoya (2.9)
useState— lazy init va funksional update — ikki muhim nozik nuqta. (1) Lazy init:useStatega berilgan boshlang'ich qiymat har render'da qayta hisoblanadi (garchi React faqat birinchisini ishlatsa ham) — agar u qimmat bo'lsa (masalanlocalStorage'dan o'qish, katta massiv qurish), o'rniga funksiya bering:useState(() => qimmatHisob()). React funksiya-argumentni faqat mount'da bir marta chaqiradi, keyingi render'larda tegmaydi. Diqqat:useState(fn)(funksiyaning o'zi) —useState(fn())(uni chaqirib qiymatini berish) emas. (2) Funksional update (updater): agar yangi qiymat eskisiga bog'liq bo'lsa,setCount(count + 1)o'rnigasetCount(c => c + 1)yozing. Sababi —countrender snapshot'idan olinadi (11.4: 2.3), shuning uchun bir handlerdasetCount(count + 1)ni ikki marta chaqirsangiz ikkalasi ham bir xil eskicount'ni ko'radi (+1 bo'lib qoladi); updater esa navbatdagi eng yangi qiymatni oladi (+2). Updater — asinxron kod, taymer, ketma-ket yangilashda stale closure'dan asosiy himoya (2.9, Misol 8).
2.4. Side effect nima — pure render vs effect
PURE RENDER (komponent funksiyasi — toza bo'lishi kerak — 11.2):
faqat props/state'dan JSX HISOBLAYDI, boshqa hech narsa qilmaydi
hech qanday "nojo'ya ish" yo'q (server chaqiruvi, DOM o'zgartirish, taymer)
SIDE EFFECT (nojo'ya ta'sir) — render'dan TASHQARIDAGI dunyoga ta'sir:
- serverdan ma'lumot olish (fetch — 12.4)
- taymer/interval o'rnatish (setInterval)
- hodisaga obuna (addEventListener, WebSocket — 5.13)
- DOM'ni qo'lda o'zgartirish (document.title, focus)
- localStorage'ga yozish
Effect'ni render PAYTIDA bajarma (komponent nopok bo'ladi, ikki marta ishlaydi — 11.2: 2.11)
Effect'ni useEffect ICHIDA bajar React uni RENDER'dan KEYIN (commit'dan so'ng) ishga tushiradi
┌──────────────────────────────────────────────────────────┐
│ Render (toza hisob) Ekran (commit) useEffect ishlaydi│
└──────────────────────────────────────────────────────────┘Side effect (nojo'ya ta'sir) —
useEffectni tushunish uchun avval shuni bilish kerak. Komponent funksiyasi toza (pure) bo'lishi kerak (11.2: 2.2): u faqat props/state'dan JSX hisoblaydi, boshqa hech narsa qilmaydi. Side effect — bu render'dan tashqaridagi dunyoga ta'sir qiladigan har qanday ish: serverdan ma'lumot olish (fetch — 12.4), taymer o'rnatish (setInterval), hodisaga obuna (addEventListener, WebSocket — 5.13), DOM'ni qo'lda o'zgartirish (document.title, focus), localStorage'ga yozish. Bu ishlarni render paytida bajarib bo'lmaydi (komponent nopok bo'ladi, StrictMode'da ikki marta ishlaydi, kutilmagan xatolar — 11.2: 2.11). O'rniga ularniuseEffectichida bajarasiz — ReactuseEffectni render va ekranga chizishdan (commit) keyin ishga tushiradi. Demak tartib: render (toza hisob) ekran yangilanadiuseEffectishlaydi. Bu — toza render va nojo'ya ta'sirni ajratishning React usuli.
2.5. useEffect anatomiyasi — sintaksis va qachon ishlaydi
useEffect(setup, dependencies):
useEffect(() => {
// SETUP — effekt mantiqi (render'dan KEYIN ishlaydi)
console.log("Effekt ishladi");
return () => {
// CLEANUP — tozalash (ixtiyoriy — keyingi effekt/unmount'dan OLDIN — 2.7)
console.log("Tozalandi");
};
}, [dependencies]); // BOG'LIQLIKLAR massivi (qachon qayta ishlashni belgilaydi — 2.6)
3 QISM:
1. setup funksiya — nima qilish (effekt)
2. cleanup (return) — orqani yig'ishtirish (ixtiyoriy)
3. dependency array — qachon ishlash (yo'q / [] / [a, b])
QACHON ISHLAYDI:
- Komponent ekranga chizilgach (mount'dan keyin)
- dependency o'zgargach (qayta render + dep boshqacha)
- Komponent yo'qolishdan oldin cleanup (unmount)
Render PAYTIDA emas, render'dan KEYIN (ekran allaqachon yangilangan)
useEffectanatomiyasi — ikki argument oladi: setup funksiya (effekt mantiqi) va dependency array (bog'liqliklar). Setup funksiya ixtiyoriy ravishda cleanup funksiya (return () => {...}) qaytarishi mumkin 2.7-bob. Demak uch qism: (1) setup — nima qilish (fetch, taymer); (2) cleanup — orqani yig'ishtirish (taymerni o'chirish, obunani bekor qilish); (3) dependency array — qachon qayta ishlash. Qachon ishlaydi: komponent ekranga chizilgach (mount'dan keyin — render paytida emas, keyin), dependency o'zgarganda (qayta render + bog'liqlik boshqacha bo'lsa), va komponent yo'qolishdan oldin cleanup ishlaydi (unmount). Eng muhim:useEffecthar doim render va ekpanga chizishdan keyin ishlaydi (foydalanuvchi avval yangi UI'ni ko'radi, keyin effekt ishga tushadi) — shuning uchun effekt ichida DOM allaqachon mavjud, va effekt foydalanuvchini "bloklamaydi". Dependency array —useEffectni to'g'ri ishlatishning kaliti 2.6-bob.
2.6. Dependency array — yo'q / [] / [deps]
DEPENDENCY ARRAY uch holat — effekt QACHON qayta ishlashni belgilaydi:
1. ARRAY YO'Q — HAR render'dan keyin ishlaydi (kamdan-kam kerak, ehtiyotkorlik):
useEffect(() => { console.log("har render") });
2. BO'SH ARRAY [] — FAQAT BIR MARTA (mount'da — komponent paydo bo'lganda):
useEffect(() => { fetchData(); }, []); // boshlang'ich yuklash uchun ideal
3. [a, b] — a yoki b O'ZGARganda ishlaydi (kuzatish):
useEffect(() => { fetchUser(userId); }, [userId]); // userId o'zgarsa qayta yukla
┌──────────────┬─────────────────────────────────────────────┐
│ deps │ Effekt qachon ishlaydi │
├──────────────┼─────────────────────────────────────────────┤
│ (yo'q) │ HAR render'dan keyin │
│ [] │ faqat 1 marta (mount) │
│ [a, b] │ mount + a yoki b o'zgarganda │
└──────────────┴─────────────────────────────────────────────┘
QOIDA: effekt ICHIDA ishlatilgan har bir o'zgaruvchi (props/state) deps'da BO'LISHI shart
ESLint (exhaustive-deps) yetishmagan bog'liqlikni ogohlantiradi — quloq sol! (2.9)Dependency array —
useEffectni qachon qayta ishlashni belgilaydi, uch holat: (1) array yo'q — har render'dan keyin ishlaydi (kamdan-kam to'g'ri, ehtiyotkorlik talab qiladi); (2) bo'sh[]— faqat bir marta, mount'da (komponent birinchi paydo bo'lganda) — boshlang'ich ma'lumot yuklash, bir martalik obuna uchun ideal; (3)[a, b]—ayokibo'zgarganda ishlaydi (masalan[userId]—userIdo'zgarsa ma'lumotni qayta yuklash). Eng muhim qoida: effekt ichida ishlatilgan har bir reaktiv qiymat (props, state, ulardan hosil bo'lgan narsa) dependency array'da bo'lishi shart — aks holda effekt eski qiymatlarni "ko'radi" (stale closure — 2.9).eslint-plugin-react-hooksningexhaustive-depsqoidasi yetishmagan bog'liqlikni ogohlantiradi — bu ogohlantirishni e'tiborsiz qoldirmang (deps'ni qo'lda "aldamang"). Agar effekt juda tez-tez ishlasa, sababi odatda — object/function dependency 2.9-bob yoki effekt umuman kerak emas 2.10-bob.
2.6a. Effekt ichida async — nega setup async bo'lolmaydi
setup funksiyaning O'ZINI async qilib bo'lmaydi:
useEffect(async () => { // async funksiya Promise qaytaradi
const data = await fetch(...); // React esa cleanup FUNKSIYA kutadi (Promise emas)
}, []); // cleanup ishlamaydi, ogohlantirish
async ishni ICHKI funksiyada bajar (setup'ning o'zi sinxron qoladi):
useEffect(() => {
let ignore = false; // race himoyasi (Misol 3)
async function load() {
const data = await fetchUser(userId);
if (!ignore) setUser(data); // faqat hali aktual bo'lsa
}
load();
return () => { ignore = true; }; // cleanup — oddiy sinxron funksiya
}, [userId]);
setup HAR doim sinxron; async'ni ichki funksiyaga o'ra, keyin chaqir
Cleanup funksiya HECH QACHON async bo'lmaydi (React uni darhol chaqiradi)Effekt ichida async — keng tuzoq:
useEffect(async () => {...})deb yozib bo'lmaydi. Sababi —asyncfunksiya doim Promise qaytaradi, React esa setup'dan cleanup funksiya (yokiundefined) kutadi — Promise'ni cleanup deb ishlata olmaydi, natijada cleanup ishlamaydi va konsol ogohlantiradi. To'g'ri naqsh: setup'ning o'zini sinxron qoldirib,async/awaitishini ichki funksiyaga o'rab, uni darhol chaqirish (async function load() {...} load();), vareturnda oddiy sinxron cleanup berish. Bu naqshrace conditionhimoyasi (ignorebayrog'i yokiAbortController— Misol 3, 14) bilan birga — real fetch effektining standarti. Cleanup funksiya ham hech qachonasyncbo'lmaydi — React uni sinxron, darhol chaqiradi.
2.7. Cleanup funksiya — qachon va nega
CLEANUP (return () => {...}) — effekt "orqasini yig'ishtiradi" (resurs bo'shatadi)
QACHON ishlaydi:
- Keyingi effekt ishlashdan OLDIN (dependency o'zgarganda — eskini tozala, keyin yangisi)
- Komponent yo'qolishdan oldin (unmount — butunlay tozala)
NEGA KERAK — resurs sizib ketmasligi (memory leak) uchun:
useEffect(() => {
const id = setInterval(() => tick(), 1000); // taymer o'rnatildi
return () => clearInterval(id); // komponent yo'qolsa — taymerni O'CHIR
}, []);
// cleanup bo'lmasa: komponent yo'qolsa ham taymer ishlayveradi (leak + xato)
TIPIK CLEANUP holatlari:
- clearInterval / clearTimeout (taymer)
- removeEventListener (hodisa)
- socket.disconnect() / unsubscribe() (obuna — 5.13)
- AbortController.abort() (fetchni bekor qilish — 12.4)
StrictMode (dev) effektni IKKI marta ishga tushiradi (setupcleanupsetup)
cleanup TO'G'RI yozilgan bo'lsa, muammo yo'q (bu ataylab — leak'ni fosh qiladi — 11.2: 2.11)Cleanup funksiya —
useEffectsetup'i qaytaradigan funksiya (return () => {...}); u effekt "orqasini yig'ishtiradi" (resurslarni bo'shatadi). Qachon ishlaydi: (1) keyingi effekt ishlashdan oldin (dependency o'zgarganda — avval eskini tozala, keyin yangisini o'rnatadi); (2) komponent yo'qolishdan oldin (unmount — butunlay tozala). Nega kerak: resurs sizib ketmasligi (memory leak) uchun — masalansetIntervalo'rnatib, cleanup yozmasangiz, komponent yo'qolsa ham taymer ishlayveradi (xotira oqib ketadi, yo'q komponentning state'ini yangilamoqchi bo'lib xato beradi). Tipik cleanup holatlari:clearInterval/clearTimeout(taymer),removeEventListener(hodisa),unsubscribe()/socket.disconnect()(obuna — 5.13),AbortController.abort()(fetchni bekor qilish — 12.4). StrictMode (development) effektni ataylab ikki marta ishga tushiradi (setup cleanup setup) — agar cleanup to'g'ri yozilgan bo'lsa muammo bo'lmaydi; bu mexanizm cleanup'ni unutgan joylaringni fosh qiladi (production'da bir marta — 11.2: 2.11). Demak cleanup — ixtiyoriy emas, resurs band qiluvchi har effekt uchun majburiy.
2.8. useEffect — "sinxronlash" modeli (lifecycle emas)
ESKI (NOTO'G'RI) MENTAL MODEL — "hayot sikli" (lifecycle):
"useEffect(() => {}, []) — bu componentDidMount" CHALKASH va xato keltiradi
YANGI (TO'G'RI) MENTAL MODEL — "SINXRONLASH" (synchronization):
"useEffect — komponentni TASHQI tizim bilan SINXRON ushlab turish"
Misol: chat xonasiga ulanish (roomId state'ga qarab):
useEffect(() => {
const conn = connectToRoom(roomId); // SINXRON: roomId qanday bo'lsa, shu xonaga ulan
return () => conn.disconnect(); // roomId o'zgarsa: eskidan uzil, yangiga ulan
}, [roomId]);
roomId="A": ulanish A. roomId="B" bo'ldi: A'dan uzil (cleanup) B'ga ulan (setup)
React effektni UI'ni state bilan sinxron ushlagandek, tashqi tizimni ham sinxron ushlaydi
"Effekt qachon ishlaydi?" emas, "effekt NIMANI sinxron ushlaydi?" deb o'yla
deps — "qaysi qiymat o'zgarsa qayta sinxronlash kerak" (lifecycle vaqti emas)
useEffect— sinxronlash modeli — bu hookni to'g'ri tushunishning kaliti. Ko'p dasturchiuseEffectni eski class hayot sikli (lifecycle —componentDidMount/Update/Unmount) deb o'ylaydi — bu chalkash va xatoga olib keladi. To'g'ri model:useEffect— komponentni tashqi tizim bilan sinxron ushlab turadi. Masalan, chat xonasiga ulanish:roomIdstate'i"A"bo'lsa, A xonasiga ulanasiz;roomId"B"bo'ldi — React avtomatik A'dan uziladi (cleanup) va B'ga ulanadi (setup). Siz "qachon ulanish/uzilish"ni emas, "qaysi xonaga ulangan bo'lishim kerak" ni tasvirlaysiz — React qolganini qiladi (xuddiUI = f(state)— tashqi tizim ham state bilan sinxron). Demak "effekt qachon ishlaydi?" deb emas, "effekt nimani tashqi dunyo bilan sinxron ushlaydi?" deb o'ylash kerak; dependency array — "qaysi qiymat o'zgarsa qayta sinxronlash kerak" (lifecycle vaqti emas). Bu mental model effektlarni to'g'ri yozish va tuzoqlardan 2.9-bob qochishning asosi.
2.9. useEffect tuzoqlari — infinite loop va stale closure
TUZOQ 1 — INFINITE LOOP (cheksiz tsikl):
useEffect(() => { setCount(count + 1); }); // deps yo'q har render setX render ...
useEffect(() => { setData(fetch()); }, [data]); // data o'zgaradi effekt data ...
to'g'ri deps: [] (bir marta) yoki kerakli bog'liqlik (object dep'dan ehtiyot bo'l)
TUZOQ 2 — OBJECT/FUNCTION DEPENDENCY (har render'da yangi havola):
const options = { id: 5 }; // har render'da YANGI obyekt (yangi havola)
useEffect(() => {...}, [options]); // har render'da "o'zgargan" deb ko'rinadi tsikl
primitiv dep: }, [options.id]) yoki obyektni effekt ichida yarat / useMemo 11.6-bob
TUZOQ 3 — STALE CLOSURE (eskirgan qiymat — eng nozik):
useEffect(() => {
const id = setInterval(() => setCount(count + 1), 1000); // count MOUNT'dagi qiymatda QOTGAN
return () => clearInterval(id);
}, []); // count har doim 0 (effekt 1 marta yaratilgan, count o'sha render'dan — 11.4: 2.3)
updater funksiya: setInterval(() => setCount(c => c + 1), 1000) // c — har doim yangi (11.4: 2.6)
Ko'p tuzoq deps'ni "aldash"dan keladi ESLint exhaustive-deps'ga quloq sol (2.6)
useEffecttuzoqlari — junior'ning eng katta xatolari shu yerda. Tuzoq 1 — infinite loop: effekt ichida state'ni yangilab, o'sha state'ni deps'ga qo'ysangiz (yoki deps yo'q bo'lsa) — render effekt setState render effekt... cheksiz tsikl; yechim — to'g'ri deps ([]yoki kerakli bog'liqlik). Tuzoq 2 — object/function dependency: komponent ichida yaratilgan obyekt/funksiya har render'da yangi havola oladi (11.4: 2.7), shuning uchun uni deps'ga qo'ysangiz React har doim "o'zgargan" deb ko'radi tsikl; yechim — primitiv dep ([options.id]), yoki obyektni effekt ichida yarat, yokiuseMemo/useCallback11.6-bob. Tuzoq 3 — stale closure (eng nozik): effekt[]deps bilan bir marta yaratiladi va ichidagi state qiymati o'sha render'dan qotib qoladi (11.4: 2.3 snapshot) — masalansetIntervalichidagicounthar doim 0; yechim — updater funksiya (setCount(c => c + 1)—char doim eng yangi — 11.4: 2.6). Ko'p tuzoq deps'ni "aldash"dan (qo'lda noto'g'ri yozish) kelib chiqadi —exhaustive-depsESLint qoidasiga quloq sol (u to'g'ri yo'lni ko'rsatadi).
2.10. Qachon useEffect KERAK EMAS (muhim!)
KENG XATO: hamma narsaga useEffect ishlatish (react.dev maxsus ogohlantiradi)
KERAK EMAS — HOSILANgan ma'lumot (state'dan hisoblanadi):
const [first, setFirst] = useState(""); const [last, setLast] = useState("");
const [full, setFull] = useState("");
useEffect(() => { setFull(first + " " + last); }, [first, last]); // ortiqcha render + effekt
const full = first + " " + last; // render PAYTIDA hisobla (state EMAS — 11.4: 2.14)
KERAK EMAS — HODISAGA javob (event handler'da qil):
useEffect(() => { if (submitted) sendData(); }, [submitted]); // chalkash, ortiqcha state
function handleSubmit() { sendData(); } // to'g'ridan handler'da
useEffect QACHON KERAK (haqiqiy side effect — tashqi tizim bilan sinxronlash):
Serverdan ma'lumot olish (mount'da yoki id o'zgarganda — 12.4)
Tashqi tizimga obuna (WebSocket, event listener, taymer)
DOM bilan qo'lda ishlash (title, focus, o'lchov)
"Bu effekt tashqi dunyo bilan sinxronlaydimi?" — YO'Q bo'lsa, effekt KERAK EMAS
Derived state'ni render'da hisobla; hodisani handler'da qil (effekt emas)Qachon
useEffectKERAK EMAS — react.dev maxsus "You Might Not Need an Effect" sahifasi bilan ogohlantiradigan keng xato. Ikki asosiy noto'g'ri ishlatish: (1) hosilangan (derived) ma'lumotni effekt bilan hisoblash — masalanfirst+last'danfullni effektda hisoblab, state'ga saqlash — bu ortiqcha (qo'shimcha render, sinxronlash muammosi); to'g'risi — render paytida hisoblash (const full = first + " " + last— state emas — 11.4: 2.14); (2) hodisaga javobni effekt bilan boshqarish — masalansubmittedstate'ni kuzatib effektda yuborish — chalkash; to'g'risi — to'g'ridan event handlerda qilish (handleSubmit).useEffectqachon haqiqatan kerak: faqat haqiqiy side effect — tashqi tizim bilan sinxronlash: serverdan ma'lumot 12.4-bob, tashqi obuna (WebSocket/taymer/listener), DOM bilan qo'lda ishlash (title/focus). Oltin test savoli: "bu effekt komponentni tashqi dunyo bilan sinxronlaydimi?" — javob "yo'q" bo'lsa (faqat ma'lumot o'zgartirish, hisoblash), effekt kerak emas. Bu bilim — keraksiz effektlardan (sekin, xato manbai) qutilishning va senior darajasida kod yozishning kaliti.
2.11. useContext — props drilling'siz ma'lumot ulashish
MUAMMO — PROPS DRILLING (props'ni ko'p qatlam orqali "burg'ulab" o'tkazish):
App (theme) Page (theme) Layout (theme) Sidebar (theme) Button (theme)
// theme faqat Button'ga kerak, lekin HAR qatlamdan qo'lda uzatamiz (zerikarli, mo'rt)
YECHIM — CONTEXT (markaziy "radio to'lqini" — istalgan chuqurlikdan o'qiladi):
1. Context yarat (alohida faylda):
const ThemeContext = createContext("light"); // default qiymat
2. Provider bilan o'ra (ma'lumot manbai — yuqorida):
<ThemeContext.Provider value={theme}>
<App /> {/* App va uning butun ostki daraxti theme'ni o'qiy oladi */}
</ThemeContext.Provider>
// React 19: to'g'ridan <ThemeContext value={theme}> (.Provider'siz)
3. Istalgan bola o'qiydi (props drilling'siz):
const theme = useContext(ThemeContext); // to'g'ridan oladi (qatlamlar oraliq emas)
QACHON Context: theme, til (i18n), autentifikatsiya (user), savat — GLOBAL/yarim-global ma'lumot
Context — props drilling'ni yo'qotadi, LEKIN tez-tez o'zgaradigan ma'lumotga — ehtiyotkorlik
(Provider value o'zgarsa, BARCHA consumer re-render — katta state uchun Redux/Zustand 12.2)
useContext— props drilling muammosini hal qiladi. Props drilling — ma'lumotni (masalantheme) faqat chuqurdagi bir komponentga yetkazish uchun har oraliq qatlamdan qo'lda uzatish (App Page Layout Sidebar Button) — zerikarli, mo'rt (oraliq komponentga keraksiz props), o'zgartirish qiyin. Context buni hal qiladi (markaziy "radio to'lqini"): (1)createContext(default)bilan kontekst yaratasiz (alohida faylda); (2)<Context.Provider value={...}>bilan ma'lumot manbaini yuqorida o'rab qo'yasiz — ostidagi butun daraxt uni o'qiy oladi (React 19'da.Providersiz, to'g'ridan<Context value={...}>); (3) istalgan chuqurlikdagi bolauseContext(Context)bilan to'g'ridan oladi (oraliq qatlamlar bilmaydi ham). Qachon Context: yarim-global ma'lumot — theme, til (i18n — 8.30), autentifikatsiya (joriy user), savat. Muhim ogohlantirish: Context props drilling'ni yo'qotadi, lekin Provider'ningvalue'si o'zgarganda barcha consumer re-render bo'ladi — shuning uchun tez-tez o'zgaradigan katta state uchun Context o'rniga maxsus vositalar (Redux/Zustand — 12.2, 12.5) yoki Context'ni bo'lib ishlatish afzal 11.11-bob.
2.11a. Context — default, ko'p context va performance (split)
DEFAULT QIYMAT — createContext(default) argumenti FAQAT Provider TOPILMAGANDA ishlaydi:
const ThemeContext = createContext("light"); // Provider yo'q daraxtda "light"
// Provider bilan o'ralgan bo'lsa — default e'tiborga olinmaydi (value ishlatiladi)
// createContext(null) + custom hook'da tekshirish — Provider'siz ishlatishni tutadi (Xato 5)
KO'P CONTEXT — bir ilovada bir nechta mustaqil context (ular ustma-ust o'raladi):
<AuthProvider>
<ThemeProvider>
<App /> {/* App ham auth, ham theme'ni o'qiy oladi */}
</ThemeProvider>
</AuthProvider>
har biri o'z mas'uliyati uchun (auth, theme, til) — aralashtirilmaydi
PERFORMANCE — CONTEXT SPLIT (bo'lish): value o'zgarsa BARCHA consumer re-render:
<Ctx value={{ user, theme, cart, setCart }}> // cart o'zgarsa — user o'quvchilari ham re-render
Alohida context: <UserCtx> + <ThemeCtx> + <CartCtx> // faqat kerakli qism re-render
value'ni useMemo bilan barqarorlashtir 11.6-bob — har render'da yangi obyekt bermaslik
Tez o'zgaradigan qism (masalan input value) — alohida context yoki state pastroqda
Katta global state — Redux/Zustand context'dan ko'ra optimallashgan (12.2, 12.5)Context — default, ko'p context va performance — uchta amaliy nozik nuqta. (1) Default qiymat:
createContext(default)ning argumenti faqat komponent daraxtda hech qanday Provider bilan o'ralmagan bo'lsa ishlaydi; Provider bor bo'lsa, uningvalue'si ishlatiladi va default e'tiborga olinmaydi. Ko'p loyihadacreateContext(null)qilib, custom hook ichida "Provider yo'qmi?" deb tekshirish afzal (Provider'siz ishlatilsa — aniq xato beradi, Xato 5). (2) Ko'p context: ilovada bir nechta mustaqil context bo'lishi normal (auth, theme, til) — ular Provider'lar sifatida ustma-ust o'raladi; har biri o'z mas'uliyati uchun, aralashtirilmaydi. (3) Performance / context split: Provider'ningvalue'si o'zgarganda hamma consumer re-render bo'ladi — shuning uchun bog'liq bo'lmagan ma'lumotlarni bitta katta context'ga tiqmang, alohida context'larga bo'ling (UserContext+ThemeContext+CartContext), vavalueobyektini har render'da yangidan yaratmaslik uchunuseMemobilan barqarorlashtiring 11.6-bob. Tez-tez o'zgaradigan (input kabi) qismni alohida ajratish yoki state'ni pastroqqa tushirish re-render'ni kamaytiradi.
2.12. useRef — DOM elementiga to'g'ridan kirish
useRef — DOM elementiga "ishora" (React'dan tashqari to'g'ridan kirish kerak bo'lganda):
function SearchInput() {
const inputRef = useRef(null); // 1. ref yarat (boshlang'ich null)
useEffect(() => {
inputRef.current.focus(); // 3. DOM metodi (.current — haqiqiy element)
}, []); // mount'da fokusni inputga qo'y
return <input ref={inputRef} />; // 2. ref'ni elementga ula
}
REF + DOM tipik holatlar:
- .focus() / .blur() (fokus boshqaruvi)
- .scrollIntoView() (elementga skroll)
- element o'lchovi (.offsetWidth, getBoundingClientRect)
- <video>/<audio> .play()/.pause(), canvas, 3-tomon kutubxona (chart, map)
ref.current — render'dan KEYIN to'ladi (DOM mavjud bo'lgach) useEffect ichida ishlat
DOM'ni React boshqaradi; ref FAQAT React qila olmaydigan narsaga (fokus, skroll, o'lchov)
React 19: ref oddiy prop (forwardRef ko'p holda kerak emas — 11.12)
useRef— DOM kirish — React odatda DOM'ni o'zi boshqaradi (deklarativ), lekin ba'zan DOM elementiga to'g'ridan kirish kerak bo'ladi (fokus, skroll, o'lchov, media play) — buning uchunuseRef. Uch qadam: (1)const inputRef = useRef(null)(ref obyekt yaratiladi); (2)<input ref={inputRef} />(ref elementga ulanadi); (3)inputRef.currentorqali haqiqiy DOM elementiga kirib, uning metodlarini chaqirasiz (.focus(),.scrollIntoView()). Tipik holatlar: fokus boshqaruvi (.focus()/.blur()), elementga skroll (.scrollIntoView()), o'lchov (.offsetWidth,getBoundingClientRect()), media (<video>.play()), 3-tomon kutubxonalarni DOM'ga ulash (chart, xarita — 8.28). Muhim:ref.currentfaqat render'dan keyin (DOM mavjud bo'lgach) to'ladi — shuning uchun ungauseEffectichida yoki hodisa handlerida murojaat qiling (render paytidanull). DOM'ni asosan React boshqaradi — ref'ni faqat React qila olmaydigan narsaga ishlating (UI'ni ref bilan o'zgartirmang — bu state'ning ishi). React 19'daref— oddiy prop (forwardRefko'p holda kerak emas — 11.12).
2.13. useRef — render'siz qiymat saqlash (mutable)
useRef — DOM'dan tashqari: RE-RENDER'SIZ o'zgaradigan qiymat saqlash (cho'ntak daftarchasi)
useState vs useRef:
┌──────────────┬─────────────────────┬──────────────────────────┐
│ │ useState │ useRef │
├──────────────┼─────────────────────┼──────────────────────────┤
│ o'zgarsa │ RE-RENDER qiladi │ re-render qilMAYDI │
│ qiymat │ render'lar orasida │ render'lar orasida │
│ │ saqlanadi │ saqlanadi │
│ o'qish/yozish│ [val, setVal] │ ref.current (to'g'ridan) │
│ uchun │ UI'da ko'rinadigan │ UI'ga ta'sir qilmaydigan │
└──────────────┴─────────────────────┴──────────────────────────┘
TIPIK (render'siz qiymat):
- interval/timeout ID saqlash (keyin tozalash uchun):
const idRef = useRef(null);
idRef.current = setInterval(...); // saqlaymiz; o'zgarishi re-render keltirmaydi
- oldingi qiymatni eslab qolish (previous value)
- "birinchi render'mi?" bayroq; render sonini sanash (UI'ga chiqarmasdan)
ref.current'ni render PAYTIDA o'qima/yozma (UI bilan sinxron emas) hodisa/effekt ichida
Qoida: UI'ga TA'SIR qiladigan useState; ko'rinmaydigan "yon" qiymat useRef
useRef— render'siz qiymat saqlash —useRefning ikkinchi vazifasi: DOM'dan tashqari, re-render keltirmasdan o'zgaradigan qiymat saqlash ("cho'ntak daftarchasi").useStatevsuseRef: ikkalasi ham qiymatni render'lar orasida saqlaydi, lekinuseStateo'zgarganda re-render qiladi (UI yangilanadi),useRefesa re-render qilmaydi (ref.currentni o'zgartirish jim — UI'ga ta'sir qilmaydi). Tipik render'siz holatlar: interval/timeout ID'ni saqlash (keyinclearIntervaluchun), oldingi qiymatni eslab qolish (previous value), "birinchi render'mi?" bayrog'i, render sonini UI'ga chiqarmasdan sanash. Ikki qoida: (1)ref.currentni render paytida o'qima/yozma (u UI bilan sinxron emas, snapshot kafolatini buzadi) — faqat hodisa handler yokiuseEffectichida; (2) tanlov qoidasi — qiymat o'zgarganda UI yangilanishi kerakmi? HauseState; yo'q (ko'rinmaydigan "yon" qiymat)useRef. Bu farqni tushunish ikki hookni to'g'ri ishlatishning kaliti.
2.13a. Ref'ni komponentga uzatish — ref prop va forwardRef
MUAMMO: ref oddiy prop kabi bola KOMPONENTGA o'tmaydi (faqat DOM elementga ulanadi):
<MyInput ref={r} /> // r — MyInput'ning ICHKI <input>'iga qanday yetadi?
REACT 19 (yangi, sodda) — ref ODDIY PROP:
function MyInput({ ref, ...props }) {
return <input ref={ref} {...props} />; // ref'ni to'g'ridan ichki DOM'ga uzatamiz
}
// <MyInput ref={r} /> r.current — ichki <input> DOM elementi
REACT 18 va oldin — forwardRef bilan o'rash kerak edi:
const MyInput = forwardRef((props, ref) => {
return <input ref={ref} {...props} />; // ref ikkinchi argument sifatida keladi
});
Nega kerak: ota komponent bola ichidagi DOM'ga (fokus, skroll) yetishi uchun
React 19'da forwardRef kerak emas (ref — oddiy prop); eski kodda hali uchraydi (11.12)Ref'ni komponentga uzatish —
refoddiy prop kabi ishlamaydi:<MyInput ref={r} />yozsangiz,ravtomatikMyInputichidagi<input>DOM'iga yetmaydi (bola — funksiya komponent, DOM emas). Bu ota komponentga bola ichidagi DOM elementiga (fokus qo'yish, skroll) yetish kerak bo'lganda muammo. React 19'da yechim sodda:ref— oddiy prop, unifunction MyInput({ ref }) { return <input ref={ref} /> }deb qabul qilib, ichki DOM'ga uzatasiz. React 18 va undan oldin buning uchunforwardRefbilan komponentni o'rash kerak edi (refcallback'ning ikkinchi argumenti sifatida kelardi). Zamonaviy React 19 loyihadaforwardRefodatda kerak emas, lekin eski kodda hali keng uchraydi — shuning uchun ikkalasini ham bilish foydali (batafsil — 11.12).
2.13b. useLayoutEffect va useId
useLayoutEffect — useEffect'ning SINXRON akasi (brauzer chizishdan OLDIN ishlaydi):
┌────────────────┬──────────────────────────────┬──────────────────────────┐
│ │ useEffect │ useLayoutEffect │
├────────────────┼──────────────────────────────┼──────────────────────────┤
│ qachon │ brauzer chizgandan KEYIN │ chizishdan OLDIN (sinxron)│
│ bloklaydimi │ yo'q (foydalanuvchi ko'radi) │ ha (chizishni kutkazadi) │
│ qachon kerak │ deyarli HAMMA holat │ DOM O'LCHASH tuzatish │
└────────────────┴──────────────────────────────┴──────────────────────────┘
useLayoutEffect nima uchun: DOM o'lchab (masalan tooltip balandligi), DARHOL joyini
to'g'rilash kerak bo'lganda — useEffect ishlatilsa, foydalanuvchi "sakrashni" ko'radi:
useLayoutEffect(() => {
const { height } = ref.current.getBoundingClientRect(); // DOM'ni o'lcha
setTooltipTop(-height); // chizishdan OLDIN joyla sakrash yo'q
}, []);
DEFAULT — useEffect; useLayoutEffect faqat "sakrash" (flicker) bo'lsa (u UI'ni sekinlatadi)
useId — barqaror, noyob ID (label input bog'lash, SSR mos):
function Field() {
const id = useId(); // masalan ":r0:"
return <><label htmlFor={id}>Ism</label><input id={id} /></>;
}
useId — LIST key uchun EMAS (u — key emas); a11y (label/input, aria) ID'lari uchun
useLayoutEffectvauseId— ikki maxsus hook.useLayoutEffect—useEffectning sinxron akasi: farqi qachon ishlashida.useEffectbrauzer ekranga chizgandan keyin ishlaydi (foydalanuvchini bloklamaydi);useLayoutEffectchizishdan oldin, sinxron ishlaydi (brauzer uni kutadi). Deyarli har doimuseEffectto'g'ri tanlov.useLayoutEffectfaqat bitta holat uchun: DOM'ni o'lchab (masalan tooltip balandliginigetBoundingClientRectbilan) darhol joyini to'g'rilash kerak bo'lganda —useEffectishlatsangiz, foydalanuvchi bir lahza noto'g'ri joyni, keyin "sakrashni" (flicker) ko'radi;useLayoutEffectesa chizishdan oldin to'g'rilaydi. U UI'ni bloklab sekinlatishi mumkin — shuning uchun defaultuseEffect,useLayoutEffectni faqat vizual sakrash muammosida.useId— barqaror, noyob identifikator generatsiya qiladi (htmlForidbog'lash,aria-*atributlari uchun), va server rendering (SSR) bilan mos (server va klient bir xil ID beradi).useId— ro'yxat (list)key'lari uchun emas (buni ma'lumotdan oling — 11.3); u faqat qulaylik (a11y) ID'lari uchun.
2.13c. Class hayot sikli hook mapping
ESKI class metodi YANGI hook ekvivalenti
┌────────────────────────────┬──────────────────────────────────────────────┐
│ componentDidMount() │ useEffect(() => {...}, []) │
│ componentDidUpdate() │ useEffect(() => {...}, [dep]) (dep o'zgarsa) │
│ componentWillUnmount() │ useEffect(() => { return () => {...} }, []) │
│ this.state / setState │ useState / useReducer 11.6-bob │
│ this.instanceVar (render'siz)│ useRef 2.13-bob │
│ shouldComponentUpdate │ React.memo + useMemo/useCallback 11.11-bob │
└────────────────────────────┴──────────────────────────────────────────────┘
Bir useEffect = mount + update + unmount BIRGA (class'da 3 ta metod edi — 2.1)
"Sikl metodi"dek emas, "sinxronlash"dek o'yla 2.8-bob — mapping faqat migratsiya uchunClass hayot sikli hook mapping — eski class kodni hooklarga ko'chirayotganingizda foydali xarita:
componentDidMountuseEffect(fn, []);componentDidUpdateuseEffect(fn, [dep])(bog'liqlik o'zgarganda);componentWillUnmountuseEffectning cleanup funksiyasi (return () => {...});this.state/setStateuseState/useReducer11.6-bob;thisustidagi render'siz o'zgaruvchiuseRef2.13-bob;shouldComponentUpdateoptimizatsiyasiReact.memo+useMemo/useCallback11.11-bob. Muhim ogohlantirish: bu jadval faqat migratsiyani tushunish uchun —useEffectni haqiqatan tushunishda uni "hayot sikli metodi"dek emas, sinxronlashdek 2.8-bob qabul qiling. BittauseEffectmount + update + unmount mantiqini bir joyda birlashtiradi (class'da uch alohida metod edi — 2.1) — bu hooklar sodaligining asosiy sababi.
2.14. Hooklar xulosasi — qaysi birini qachon
┌─────────────┬──────────────────────────────────────────────────────┐
│ Hook │ Qachon ishlatish │
├─────────────┼──────────────────────────────────────────────────────┤
│ useState │ UI'ga ta'sir qiladigan o'zgaradigan ma'lumot 11.4-bob │
│ useEffect │ tashqi tizim bilan sinxronlash (fetch, taymer, obuna) │
│ useContext │ yarim-global ma'lumot (theme, auth) — drilling'siz │
│ useRef │ DOM kirish YOKI render'siz "yon" qiymat │
│ useLayoutEffect│ DOM o'lchash chizishdan OLDIN tuzatish (2.13b) │
│ useId │ barqaror noyob ID (label/input, a11y — 2.13b) │
│ useReducer │ murakkab/bog'liq state mantiqi 11.6-bob │
│ useMemo │ qimmat hisobni keshlash (11.6, 11.11) │
│ useCallback │ funksiyani keshlash (11.6, 11.11) │
│ custom hook │ mantiqni qayta ishlatish 11.7-bob │
└─────────────┴──────────────────────────────────────────────────────┘
Avval ENG SODDA yechim (useState + render'da hisob) murakkablashsa hook qo'sh
Hookni "shunchaki" ishlatma — har birining aniq sababi bo'lsin (effekt KERAK EMAS — 2.10)Hooklar xulosasi — qaysi hookni qachon ishlatish bo'yicha yo'l xaritasi.
useState— UI'ga ta'sir qiladigan o'zgaradigan ma'lumot 11.4-bob.useEffect— tashqi tizim bilan sinxronlash (fetch, taymer, obuna — faqat haqiqiy side effect, 2.10).useContext— yarim-global ma'lumot (theme, auth) props drilling'siz.useRef— DOM kirish yoki render'siz "yon" qiymat. Va keyingi boblarda:useReducer(murakkab/bog'liq state — 11.6),useMemo/useCallback(keshlash, performance — 11.6, 11.11), custom hook (mantiqni qayta ishlatish — 11.7). Ikki tamoyil: (1) har doim eng sodda yechimdan boshla (oddiyuseState+ render'da hisoblash — 11.4: 2.14) va faqat zarurat tug'ilganda murakkabroq hook qo'sh; (2) hookni "shunchaki, hamma ishlatadi" deb ishlatma — har birining aniq sababi bo'lsin (ayniqsauseEffect— ko'p hollarda kerak emas — 2.10). To'g'ri hook tanlash — toza, tez, xatosiz React kodning asosi.
3. Sintaksis — tez ma'lumotnoma
EFFECT 2.5-bob: useEffect(() => { ...; return () => {cleanup} }, [deps])
DEPS 2.6-bob: (yo'q) har render | [] bir marta(mount) | [a,b] a/b o'zgarganda
CLEANUP 2.7-bob: return () => { clearInterval(id) / unsubscribe() / abort() }
FETCH (Misol 3): useEffect(() => { let active=true; fetch().then(d => active && setData(d));
return () => { active=false } }, [id])
CONTEXT 2.11-bob: const Ctx=createContext(def) | <Ctx.Provider value={x}> | useContext(Ctx)
REF DOM 2.12-bob: const r=useRef(null) | <input ref={r}/> | r.current.focus()
REF QIYMAT 2.13-bob:const r=useRef(0) | r.current = 5 // re-render YO'Q
UPDATER 2.9-bob: setInterval(() => setX(prev => prev+1), 1000) // stale closure'dan qochish
LAZY INIT(2.3a): useState(() => qimmatHisob()) // FAQAT mount'da; useState(fn()) EMAS
ASYNC (2.6a): useEffect(() => { async function f(){...} f(); return ()=>{} }, [dep])
LAYOUT (2.13b): useLayoutEffect(() => { o'lcha; joyla }, []) // chizishdan OLDIN (flicker yo'q)
useId (2.13b): const id = useId() | <label htmlFor={id}/> <input id={id}/>
REF PROP (2.13a): function In({ref}){ return <input ref={ref}/> } // R19; R18: forwardRef4. Batafsil kod namunalari
Misol 1 — useEffect: mount'da bir marta (2.5, 2.6)
import { useState, useEffect } from "react";
function Welcome() {
const [message, setMessage] = useState("Yuklanmoqda...");
useEffect(() => {
// Bu FAQAT mount'da (birinchi render'dan keyin) ishlaydi ([] — 2.6)
console.log("Komponent paydo bo'ldi");
setMessage("Xush kelibsiz!");
}, []); // bo'sh deps bir marta
return <h1>{message}</h1>;
}
// [] — boshlang'ich sozlash/yuklash uchun; har render'da emas (2.6)Misol 2 — useEffect: dependency o'zgarganda (2.6)
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
console.log("userId o'zgardi:", userId);
fetchUser(userId).then(setUser); // userId o'zgarganda qayta yukla
}, [userId]); // userId deps'da — o'zgarsa effekt qayta ishlaydi
if (!user) return <p>Yuklanmoqda...</p>; // shartli render (11.4: 2.12)
return <h2>{user.name}</h2>;
}
// userId effekt ichida ishlatildi deps'da BO'LISHI shart (exhaustive-deps — 2.6)Misol 3 — Data fetching: loading/error/data + cleanup (2.6, 2.7)
function Products() {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
let ignore = false; // "race condition"dan himoya (eski javobni rad et)
setLoading(true);
setError(null);
fetch("https://api.example.com/products")
.then(res => {
if (!res.ok) throw new Error("Server xatosi");
return res.json();
})
.then(json => { if (!ignore) setData(json); }) // faqat hali aktual bo'lsa
.catch(err => { if (!ignore) setError(err.message); })
.finally(() => { if (!ignore) setLoading(false); });
return () => { ignore = true; }; // cleanup: komponent yo'qolsa/qayta yuklansa — eskini rad et
}, []); // mount'da bir marta
if (loading) return <Spinner />; // 3 holat (11.4: 2.12)
if (error) return <p className="error">{error}</p>;
return <ul>{data.map(p => <li key={p.id}>{p.name}</li>)}</ul>;
}
// "ignore" bayrog'i — tez almashgan so'rovlarda eski javob yangisini bosib ketmasligi uchun
// (haqiqiy loyihada TanStack Query buni avtomatik qiladi — 12.4)Misol 4 — Cleanup: taymer (interval — 2.7, 2.9)
function Clock() {
const [time, setTime] = useState(new Date());
useEffect(() => {
const id = setInterval(() => {
setTime(new Date()); // har soniyada yangila
// Agar setTime(time) bo'lsa — stale closure (time qotgan). Bu yerda yangi obyekt — muammosiz
}, 1000);
return () => clearInterval(id); // komponent yo'qolsa — taymerni O'CHIR (leak'dan saqlanish — 2.7)
}, []); // bir marta o'rnat
return <p>Vaqt: {time.toLocaleTimeString()}</p>;
}Misol 5 — Cleanup: event listener / subscription (2.7)
function WindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
function handleResize() { setWidth(window.innerWidth); }
window.addEventListener("resize", handleResize); // obuna
return () => window.removeEventListener("resize", handleResize); // cleanup — obunani bekor qil
}, []);
return <p>Oyna kengligi: {width}px</p>;
}
// removeEventListener'da AYNAN o'sha funksiya (handleResize) berilishi shart (anonim emas)Misol 6 — DOM bilan ishlash: document.title sinxron (2.4, 2.8)
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `Bosildi: ${count} marta`; // DOM (sahifa sarlavhasi)ni state bilan sinxronla
}, [count]); // count o'zgarganda yangila (sinxronlash — 2.8)
return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}
// Sarlavha — tashqi tizim (document); useEffect uni count bilan SINXRON ushlaydi (2.8)Misol 7 — Infinite loop xatosi va tuzatish (2.9)
function BuggyVsFixed({ userId }) {
const [user, setUser] = useState(null);
// INFINITE LOOP — har render'da yangi obyekt (yangi havola "o'zgargan" effekt render ...)
// const config = { id: userId };
// useEffect(() => { fetchUser(config).then(setUser); }, [config]);
// TO'G'RI — primitiv dependency (userId — o'zgargandagina effekt)
useEffect(() => {
const config = { id: userId }; // obyektni effekt ICHIDA yarat (deps'da emas)
fetchUser(config).then(setUser);
}, [userId]); // primitiv dep — barqaror taqqoslash (2.9)
return <div>{user?.name}</div>;
}Misol 8 — Stale closure va updater bilan tuzatish (2.9)
function AutoCounter() {
const [count, setCount] = useState(0);
useEffect(() => {
const id = setInterval(() => {
// setCount(count + 1) — count MOUNT'dagidek 0 da QOTGAN har doim 01 (stale closure)
setCount(prev => prev + 1); // updater — prev har doim eng yangi (11.4: 2.6)
}, 1000);
return () => clearInterval(id);
}, []); // [] — effekt bir marta yaratiladi (count qotardi)
return <h1>{count}</h1>; // 0, 1, 2, 3... to'g'ri sanaydi
}
// Stale closure: effekt [] bilan 1 marta yaratiladi, count o'sha render snapshot'ida.
// Yechim — updater (prev =>), u React'dan eng yangi qiymatni oladi (deps'ga count qo'shmasdan)Misol 9 — useEffect KERAK EMAS: derived state (2.10)
function Cart({ items }) {
// KERAK EMAS — total'ni effekt bilan hisoblash (ortiqcha state + render):
// const [total, setTotal] = useState(0);
// useEffect(() => { setTotal(items.reduce((s, i) => s + i.price, 0)); }, [items]);
// TO'G'RI — render PAYTIDA hisobla (state emas — 11.4: 2.14, 2.10):
const total = items.reduce((sum, item) => sum + item.price, 0); // har render'da qayta hisob
const count = items.length;
return <p>{count} ta mahsulot — Jami: {total} so'm</p>;
}
// items'dan KELIB CHIQADIgan narsa — state EMAS, effekt EMAS — to'g'ridan hisobla (2.10)Misol 10 — useContext: Theme provider (2.11)
// src/context/ThemeContext.jsx
import { createContext, useContext, useState } from "react";
const ThemeContext = createContext(); // kontekst yaratamiz
export function ThemeProvider({ children }) { // o'rovchi (provider) komponent
const [theme, setTheme] = useState("light");
const toggle = () => setTheme(t => (t === "light" ? "dark" : "light"));
return (
<ThemeContext.Provider value={{ theme, toggle }}> {/* React 19: <ThemeContext value={...}> */}
{children}
</ThemeContext.Provider>
);
}
export const useTheme = () => useContext(ThemeContext); // qulay custom hook 11.7-bob
// Ishlatish — istalgan chuqurlikdagi bola (props drilling YO'Q):
function ThemeButton() {
const { theme, toggle } = useTheme(); // to'g'ridan oladi (oraliq qatlamlar bilmaydi)
return <button onClick={toggle}>Mavzu: {theme}</button>;
}
// main.jsx: <ThemeProvider><App /></ThemeProvider> butun App theme'ni o'qiy oladiMisol 11 — useContext: Auth context (2.11)
const AuthContext = createContext();
export function AuthProvider({ children }) {
const [user, setUser] = useState(null);
const login = async (email, password) => {
const data = await api.login(email, password); // 12.4
setUser(data.user);
};
const logout = () => setUser(null);
return (
<AuthContext.Provider value={{ user, login, logout }}>
{children}
</AuthContext.Provider>
);
}
export const useAuth = () => useContext(AuthContext);
// Istalgan komponentda:
function Navbar() {
const { user, logout } = useAuth();
return user
? <button onClick={logout}>Chiqish ({user.name})</button> // shartli (11.4: 2.12)
: <a href="/login">Kirish</a>;
}
// Auth — klassik Context holati (butun ilovaga kerak, kam o'zgaradigan)Misol 12 — useRef: DOM elementga fokus (2.12)
function SearchForm() {
const inputRef = useRef(null); // ref yaratamiz
useEffect(() => {
inputRef.current.focus(); // mount'da fokusni inputga qo'y (.current — DOM)
}, []);
function clearAndFocus() {
inputRef.current.value = ""; // DOM'ni to'g'ridan (faqat imperativ holatda)
inputRef.current.focus();
}
return (
<form>
<input ref={inputRef} placeholder="Qidirish..." /> {/* ref'ni elementga ulaymiz */}
<button type="button" onClick={clearAndFocus}>Tozala</button>
</form>
);
}
// Fokus — React deklarativ qila olmaydi ref bilan imperativ (2.12)Misol 13 — useRef: oldingi qiymat va interval ID (2.13)
function PreviousValue({ count }) {
const prevRef = useRef(); // render'siz qiymat saqlash
useEffect(() => {
prevRef.current = count; // har render'dan keyin joriy count'ni eslab qol
}, [count]); // (re-render keltirmaydi — 2.13)
const prev = prevRef.current; // oldingi qiymat (effekt undan oldin o'qildi)
return <p>Hozir: {count}, oldin: {prev ?? "yo'q"}</p>;
}
function Stopwatch() {
const [seconds, setSeconds] = useState(0);
const intervalRef = useRef(null); // interval ID'ni render'siz saqlaymiz
const start = () => {
if (intervalRef.current) return; // allaqachon ishlayaptimi?
intervalRef.current = setInterval(() => setSeconds(s => s + 1), 1000);
};
const stop = () => {
clearInterval(intervalRef.current);
intervalRef.current = null; // o'zgarishi re-render keltirmaydi (2.13)
};
return (
<div>
<p>{seconds}s</p>
<button onClick={start}>Boshlash</button>
<button onClick={stop}>To'xtatish</button>
</div>
);
}Misol 14 — Hammasi birga: qidiruv + debounce (useState + useEffect + useRef + cleanup)
function LiveSearch() {
const [query, setQuery] = useState("");
const [results, setResults] = useState([]);
const [loading, setLoading] = useState(false);
useEffect(() => {
if (!query.trim()) { setResults([]); return; } // bo'sh bo'lsa — qidirmaymiz
setLoading(true);
const controller = new AbortController(); // fetchni bekor qilish uchun (2.7)
// DEBOUNCE — foydalanuvchi yozishni to'xtatgandan 400ms keyin qidir (har harfda emas)
const timer = setTimeout(() => {
fetch(`/api/search?q=${query}`, { signal: controller.signal })
.then(r => r.json())
.then(data => { setResults(data); setLoading(false); })
.catch(err => { if (err.name !== "AbortError") setLoading(false); });
}, 400);
return () => { // cleanup: query o'zgarsa — eski timer va fetchni bekor qil
clearTimeout(timer); // eski debounce taymerni o'chir
controller.abort(); // eski so'rovni bekor qil (2.7)
};
}, [query]); // query o'zgarganda qayta sinxronlash (2.8)
return (
<div>
<input value={query} onChange={e => setQuery(e.target.value)} placeholder="Qidirish..." />
{loading && <small>Qidirilmoqda...</small>}
<ul>{results.map(r => <li key={r.id}>{r.title}</li>)}</ul>
</div>
);
}
// Bu naqsh — debounce + abort + cleanup — real qidiruvning standarti (12.4'da Query soddalashtiradi)5. To'g'ri va noto'g'ri holatlar
1) Hook joylashuvi
if (x) { useState(...) } / for(...) { useEffect(...) } (shart/tsikl ichida — 2.2)
komponent tepasida, shartsiz; shartni hook ICHIDA qo'y2) Dependency array
useEffect(() => { fetch(id) }, []) (id ishlatildi, deps'da yo'q — eski id — 2.6)
useEffect(() => { fetch(id) }, [id]) (exhaustive-deps)3) Cleanup
setInterval/addEventListener — cleanup yo'q (memory leak — 2.7)
return () => clearInterval(id) / removeEventListener(...)4) Stale closure
setInterval(() => setCount(count + 1), 1000) (count qotgan — 2.9)
setInterval(() => setCount(c => c + 1), 1000) (updater)5) Keraksiz effekt
useEffect(() => setFull(a + " " + b), [a, b]) (derived state — 2.10)
const full = a + " " + b (render'da hisobla)6) Object dependency
const opt = {id}; useEffect(..., [opt]) (har render yangi havola tsikl — 2.9)
[id] (primitiv) yoki obyektni effekt ichida yarat / useMemo (11.6)7) useRef vs useState
UI'da ko'rinadigan qiymat useRef'da (o'zgarsa ekran yangilanmaydi — 2.13)
UI'ga ta'sir useState; render'siz "yon" qiymat useRef6. Keng tarqalgan xatolar va yechimlari
Xato 1 — React Hook useEffect has a missing dependency: 'x'
Sababi: effekt ichida x ishlatildi, lekin deps'da yo'q 2.6-bob. Yechimi: xni deps'ga qo'sh; agar tsikl bo'lsa — sababi object/function dep (Misol 7) yoki effekt kerak emas 2.10-bob. Deps'ni qo'lda "aldama".
Xato 2 — Sahifa qotib qoladi / Maximum update depth exceeded
Sababi: infinite loop — effekt state'ni yangilab, o'sha state deps'da (yoki object dep — 2.9). Yechimi: deps'ni to'g'rila (primitiv), yoki effektni umuman olib tashla (derived — 2.10).
Xato 3 — Cannot read properties of null (reading 'focus')
Sababi: ref.current hali null (render paytida yoki element ulanmagan). Yechimi: useEffect ichida ishlat (DOM tayyor); ref.current?.focus() 2.12-bob.
Xato 4 — Taymer/listener komponent yo'qolgach ham ishlayveradi
Sababi: cleanup yo'q 2.7-bob. Yechimi: return () => clearInterval(id) / removeEventListener(...).
Xato 5 — useContext undefined qaytaradi
Sababi: komponent Provider ICHIDA emas (daraxtda yuqorida Provider yo'q — 2.11). Yechimi: ildizda (main.jsx/App) <Provider> bilan o'ra; custom hook'da tekshir (if (!ctx) throw).
Xato 6 — State eski qiymatda qotgan (setInterval/setTimeout ichida)
Sababi: stale closure 2.9-bob. Yechimi: updater funksiya (setX(prev => ...) — Misol 8), yoki kerakli qiymatni useRefda sakla.
Xato 7 — StrictMode'da effekt ikki marta ishlaydi (dev)
Sababi: bu ataylab (cleanup'ni tekshirish — 11.2: 2.11). Yechimi: to'g'ri cleanup yoz — shunda ikki marta ishlash zararsiz; bu xato emas (production'da bir marta).
7. Integratsiya — bu mavzu stack'ning qayerida uchraydi
- State 11.4-bob:
useState— birinchi hook; updater (2.9 stale closure yechimi). - useReducer/useMemo/useCallback 11.6-bob: murakkab state va keshlash hooklari.
- Custom hooks 11.7-bob: bu hooklarni birlashtirib o'z hookingni yozasiz (Misol 10
useTheme). - Data fetching 12.4-bob:
useEffect+fetch TanStack Query buni soddalashtiradi (race, cache avtomatik). - Context API 12.1-bob:
useContextchuqur kengaytmasi; Redux 12.2-bob alternativasi. - Forma 11.10-bob: controlled + effekt; React Hook Form effekt og'rig'ini kamaytiradi.
- WebSocket 5.13-bob:
useEffect+ cleanup — obuna/uzilish naqshi. - Performance 11.11-bob: keraksiz effekt/re-render; object dep muammosi 2.9-bob.
8. Eng yaxshi amaliyotlar (best practices)
- Rules of Hooks'ga rioya (tepada, shartsiz; ESLint plugin yoq — 2.2, 15.3).
exhaustive-deps'ga quloq sol (deps'ni qo'lda aldama — 2.6, Xato 1).- Har band qiluvchi effektga cleanup (taymer, listener, obuna, fetch — 2.7).
- Updater funksiya (asinxron/taymer ichida stale closure'dan qoch — 2.9).
- "Effekt kerakmi?" deb so'ra (derived state'ni render'da hisobla; hodisani handler'da — 2.10).
- Object/function dep'dan ehtiyot (primitiv dep yoki useMemo — 2.9, 11.6).
- Sinxronlash modelida o'yla (lifecycle emas — "nimani sinxron ushlaydi" — 2.8).
useContextyarim-global uchun (theme/auth; tez-tez o'zgaradigan katta state — Redux 12.2).useRefto'g'ri tanla (DOM yoki render'siz qiymat; UI'ga ta'sir useState — 2.13).- Fetch'ni Query'ga ko'chir (real loyihada
useEffect+fetch o'rniga TanStack Query — 12.4).
9. Amaliy loyiha: "Ob-havo va Vaqt Dashboard"
Bu loyiha barcha to'rt hookni birga ishlatadi — real API, taymer, global mavzu, DOM fokus.
Maqsad
Shahar ob-havosini API'dan oladigan, jonli soat ko'rsatadigan, mavzu (light/dark) almashtiradigan dashboard yarat.
Talablar (requirements)
- Jonli soat:
useEffect+setInterval+ cleanup; har soniyada yangilansin (Misol 4). - Ob-havo fetch: shahar input'iga qarab API'dan ma'lumot (loading/error/data — Misol 3).
- Debounce: shahar yozishni to'xtatgandan keyin qidir (
setTimeout+ cleanup — Misol 14). - Race himoyasi: tez almashgan so'rovlarda eski javob yangisini bosmasin (
ignore/AbortController— Misol 3, 14). - Theme Context: light/dark mavzu,
useContextbilan butun dashboard'ga (Misol 10). - Auto-focus: sahifa ochilganda shahar input'iga fokus (
useRef+useEffect— Misol 12). - Oxirgi qidiruvlar: so'nggi 5 qidiruvni ko'rsat (massiv state — 11.4: 2.9).
- document.title: joriy shahar nomini sahifa sarlavhasiga sinxronla (Misol 6).
- Cleanup to'liq: har taymer/fetch/listener tozalansin (memory leak yo'q — 2.7).
- "Effekt kerakmi?" tekshir: hosilangan qiymat (masalan formatlangan harorat)ni render'da hisobla, effektda emas 2.10-bob.
Maslahatlar (hint)
- API: ochiq ob-havo API (masalan open-meteo — kalit talab qilmaydi) yoki mock ma'lumot.
useEffectdeps'ni to'g'ri qo'y: soat[], ob-havo[city].- Debounce + AbortController + cleanup — Misol 14 naqshini ishlat.
- Theme'ni alohida
ThemeProvider+useThemehook qil (Misol 10) —main.jsxda o'ra. - Stale closure'dan ehtiyot bo'l: taymerda
setX(prev => ...)(Misol 8). - ESLint ogohlantirishlariga quloq sol (
exhaustive-deps) — ular to'g'ri yo'lni ko'rsatadi.
"Tayyor" mezonlari (acceptance criteria)
- Jonli soat ishlaydi va cleanup bor (komponent yo'qolsa taymer to'xtaydi).
- Ob-havo fetch: loading/error/data uch holati to'g'ri.
- Debounce ishlaydi (har harfda emas, to'xtagach qidiradi).
- Race condition yo'q (eski javob yangisini bosmaydi).
- Theme Context butun dashboard'ga ta'sir qiladi (drilling yo'q).
- Input mount'da avtomatik fokuslanadi.
- So'nggi qidiruvlar ro'yxati ishlaydi.
-
document.titleshahar bilan sinxron. - Hech qanday memory leak yo'q (barcha cleanup mavjud).
- Hosilangan qiymatlar render'da hisoblangan (keraksiz effekt yo'q).
Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.
10. Xulosa va keyingi bobga ko'prik
Bu bobda React hooklarini chuqur o'rgandik:
- Hook nima (class'dan o'tish — 2.1); Rules of Hooks (nega tepada, shartsiz — chaqiruv tartibi — 2.2); ko'p
useState2.3-bob, lazy init va funksional update (2.3a). - Side effect (pure render vs effect — 2.4);
useEffectanatomiyasi 2.5-bob, dependency array (yo'q/[]/[deps] — 2.6), effekt ichida async (2.6a), cleanup (resurs bo'shatish — 2.7), sinxronlash modeli (lifecycle emas — 2.8). - Tuzoqlar (infinite loop, object dep, stale closure — 2.9); qachon effekt KERAK EMAS (derived state, hodisa — 2.10).
useContext(props drilling'siz — 2.11; default/ko'p context/split — 2.11a);useRef(DOM kirish — 2.12, render'siz qiymat — 2.13, ref prop/forwardRef — 2.13a);useLayoutEffect/useId(2.13b); class hook mapping (2.13c); hooklar xulosasi 2.14-bob.
Endi siz real ilova qura olasiz: serverdan ma'lumot (useEffect+fetch), global state (useContext), DOM kirish va render'siz qiymat (useRef) — va eng muhimi, eng keng tuzoqlardan (stale closure, infinite loop, keraksiz effekt) qochishni bilasiz.
Keyingi bob — 11.6-bob: useMemo, useCallback, useReducer. Hooklar bilimini yakunlaymiz: useReducer (murakkab, bog'liq state mantiqi — useStatening kuchliroq ukasi, Redux falsafasiga ko'prik — 12.2), useMemo (qimmat hisobni keshlash — ortiqcha qayta hisoblashni to'xtatish), useCallback (funksiyani keshlash — bu bobdagi object/function dependency muammosini hal qiladi — 2.9). Bu hooklar — performance optimizatsiya 11.11-bob va katta ilova arxitekturasining poydevori.
Foydalanilgan rasmiy/ishonchli manbalar
- React rasmiy hujjati (react.dev) — "Synchronizing with Effects", "You Might Not Need an Effect", "Lifecycle of Reactive Effects", "Removing Effect Dependencies"
- react.dev —
useState,useEffect,useContext,useRefAPI reference; "Rules of Hooks", "Manipulating the DOM with Refs", "Referencing Values with Refs" - react.dev —
useState: lazy initializer va updater funksiya ("Passing an updater function", "avoiding recreating the initial state") - react.dev —
useLayoutEffect,useIdAPI reference; "Separating Events from Effects", "State as a Snapshot" - react.dev — "Passing Data Deeply with Context", "Scaling Up with Reducer and Context", "Reusing Logic with Custom Hooks"
- react.dev — React 19 release notes:
<Context>as provider,refas a prop;forwardRef(React 18 API) - MDN —
setInterval/clearInterval,AbortController,addEventListener,Element.getBoundingClientRect()
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!