Mundarija (46)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Re-render — qachon va nega (to'liq manzara)
- 2.2. Re-render ≠ DOM update (render vs commit)
- 2.3. Muammoni topish — o'lcha (React DevTools Profiler)
- 2.4. Re-render sabablari va yechimlari
- 2.5. State colocation — state'ni pastga tushir
- 2.6. React.memo chuqur — props taqqoslash
- 2.7. useMemo/useCallback — performance kontekstida
- 2.8. children prop fokusi — re-render'ni to'xtatish
- 2.9. Context optimizatsiyasi — bo'lish va value memo
- 2.10. Inline obyekt/funksiyadan qochish va key bilan reset
- 2.11. List virtualization — uzun ro'yxatlar
- 2.12. Debounce va throttle — qimmat hodisalar
- 2.13. Concurrent: useTransition va useDeferredValue
- 2.14. Bundle, rasm, web worker va Web Vitals (yuklanish + og'ir ish)
- 2.15. Suspense va SSR/streaming (yuklanish tajribasi)
- 2.16. React Compiler va performance tafakkuri
- 3. Sintaksis — tez ma'lumotnoma
- 4. Batafsil kod namunalari
- Misol 1 — Keraksiz re-render (Profiler bilan ko'rinadi — 2.1, 2.3)
- Misol 2 — React.memo bilan tuzatish (2.6)
- Misol 3 — React.memo custom comparison (2.6)
- Misol 4 — useCallback + memo to'liq (inline muammosi — 2.7, 2.10)
- Misol 5 — useMemo qimmat hisob (2.7, 11.6)
- Misol 6 — State colocation (state'ni pastga tushir — 2.5)
- Misol 7 — children trick (re-render'ni to'xtatish — 2.8)
- Misol 8 — Context bo'lish va value memo (2.9)
- Misol 9 — key bilan state reset (2.10)
- Misol 10 — List virtualization (react-window — 2.11)
- Misol 11 — Debounce qimmat qidiruv (2.12, 11.7)
- Misol 12 — useTransition (bloklamaydigan yangilanish — 2.13)
- Misol 13 — useDeferredValue (og'ir ro'yxat kechiktirish — 2.13)
- Misol 14 — Optimizatsiya jarayoni (o'lcha → tuzat → o'lcha — 2.3, 2.16)
- Misol 15 — Web Worker (o'ta og'ir hisob — main thread'ni qotirmaslik — 2.14)
- 5. To'g'ri va noto'g'ri holatlar
- 6. Keng tarqalgan xatolar va yechimlari
- 7. Integratsiya — bu mavzu stack'ning qayerida uchraydi
- 8. Eng yaxshi amaliyotlar (best practices)
- 9. Amaliy loyiha: "Katta Ma'lumotli Dashboard (Performance)"
- Maqsad
- Talablar (requirements)
- Maslahatlar (hint)
- "Tayyor" mezonlari (acceptance criteria)
- 10. Xulosa va keyingi bobga ko'prik
- Foydalanilgan rasmiy/ishonchli manbalar
11.11-bob: Performance optimizatsiya (memo, re-render)
11-QISM — Frontend: React · 11-mavzu
1. Kirish va motivatsiya
11.6-bobda memo, useMemo, useCallbackni o'rgandik va "qachon optimallashtirMaslik" tamoyilini ko'rdik. Endi shu vositalarni performance rakursidan birlashtirib, React ilovasini tezlashtirish san'atini o'rganamiz. Bu — kitobning eng nozik va eng ko'p chalkashtiriladigan mavzularidan biri: ko'p dasturchi "React sekin" deb o'ylab, har joyga memo tiqishtiradi yoki aksincha — ilova sekinlashganini sezmasdan foydalanuvchini yo'qotadi. Haqiqat — o'rtada: React odatda juda tez, lekin ba'zan (uzun ro'yxatlar, qimmat hisoblar, tez-tez re-render) maxsus optimizatsiya kerak bo'ladi. Bu bobda aynan qachon, qanday, va eng muhimi — qaysi muammoni hal qilishni o'rganamiz.
Eng muhim g'oya — bu butun bob davomida takrorlanadi: o'lchang, taxmin qilmang (measure, don't guess). React DevTools Profiler — bu mavzuning eng muhim vositasi: u qaysi komponent qancha vaqt va necha marta render bo'layotganini aniq ko'rsatadi. Optimizatsiyani "menga shu sekin tuyuldi" emas, dalilga asoslab qilasiz. Va yana bir tamoyil: avval to'g'ri, keyin tez — ishlaydigan kod yozasiz, muammo bo'lsa uni o'lchab topasiz, so'ng aniq joyini tezlashtirasiz. Premature optimization (oldindan, kerak bo'lmasdan optimallashtirish) — kodni murakkablashtiradi va ko'pincha foyda bermaydi (11.6: 2.13).
Bu bob: re-render qachon va nega bo'ladi (to'liq manzara), re-render ≠ DOM update (render vs commit — 11.2: 2.2), muammoni topish (React DevTools Profiler, "highlight updates"), re-render sabablari (parent, context, yangi obyekt/funksiya props, state joyi), state colocation (state'ni pastga tushirish), React.memo chuqur (props taqqoslash, custom comparison), useMemo/useCallback performance kontekstida (referential equality — 11.6: 2.9), children prop fokusi (re-render'ni to'xtatish trick), Context optimizatsiyasi (bo'lish, value memo), inline obyekt/funksiyadan qochish, key bilan state reset, list virtualization (uzun ro'yxatlar — react-window), debounce/throttle (qimmat hodisalar), concurrent (useTransition, useDeferredValue), bundle/rasm/web worker optimizatsiya va Web Vitals (LCP/INP/CLS), Suspense va SSR/streaming (yuklanish tajribasi), va React Compiler (avto-memoizatsiya). Bularning har biri to'liq va amaliy holatda ochib beriladi.
O'xshatish: React performance — bu shifokorning ish uslubi. Yomon shifokor (junior dasturchi) — bemorni ko'rmasdan, "ehtimol shu kasallik" deb barcha dorilarni yozib beradi (har joyga
memo/useMemo— ko'p, lekin foydasiz, ba'zan zararli). Yaxshi shifokor (senior) — avval tashxis qo'yadi: analiz oladi, o'lchovni ko'radi (React DevTools Profiler), aniq muammoni topadi, so'ng aynan o'sha kasallikka davo beradi (faqat kerakli joyni optimallashtiradi). Premature optimization — sog'lom odamga davolanish kabi (zarari foydasidan ko'p). Va eng yaxshi shifokor biladi: tana o'zi ko'p narsani tuzatadi (React o'zi tez) — faqat haqiqiy muammoga aralashadi.
Nega muhim?
- Foydalanuvchi tajribasi — sekin ilova = tark etilgan foydalanuvchi (har 100ms muhim — Core Web Vitals).
- Katta ilovada zarur — uzun ro'yxatlar, murakkab UI, tez-tez yangilanish — optimizatsiyasiz sekinlashadi.
- Senior ko'nikma — "o'lchang, taxmin qilmang" tafakkuri — junior'ni senior'dan ajratadi (dalilga asoslaning).
- Boshqa bilimni birlashtiradi — memo 11.6-bob, code splitting 11.8-bob, hooklar 11.5-bob — hammasi performance'da.
2. Nazariya — chuqur tushuntirish
2.1. Re-render — qachon va nega (to'liq manzara)
KOMPONENT QAYTA RENDER BO'LADI (3 sabab):
1. STATE o'zgardi (useState/useReducer — 11.4: 2.4)
2. PROPS o'zgardi (ota yangi props berdi)
3. OTA re-render bo'ldi → BARCHA bolalari ham (props o'zgarmagan bo'lsa HAM!)
4. (Context qiymati o'zgardi → o'sha Context'ni ishlatgan hamma — 11.5: 2.11)
┌────────────────────────────────────────────────────────────┐
│ App render │
│ ├─ Header ← App render bo'lsa, BU HAM render (props o'zg- │
│ ├─ Content ← armagan bo'lsa ham — default xulq) │
│ └─ Footer ← HAM render │
│ → bitta state o'zgarsa — butun shox render bo'lishi mumkin │
└────────────────────────────────────────────────────────────┘
❗ Eng KENG noto'g'ri tushuncha: "props o'zgarsa bola render bo'ladi"
→ ASLIDA: OTA render bo'lsa, bola HAM render (props tekshirilmaydi — memo'siz)
❗ Re-render "yomon" emas — React tez; muammo faqat KERAKSIZ QIMMAT render (2.2)Re-render qachon va nega — performance'ni tushunishning birinchi qadami. Komponent uch sababga ko'ra qayta render bo'ladi: (1) state o'zgardi (
useState/useReducer— 11.4: 2.4); (2) props o'zgardi; (3) ota re-render bo'ldi → uning barcha bolalari ham re-render bo'ladi (props o'zgarmagan bo'lsa ham — bu React'ning default xulqi); (4) ishlatilayotgan Context qiymati o'zgardi → o'sha Context'ni ishlatgan barcha komponent (11.5: 2.11). Eng keng noto'g'ri tushuncha: ko'p dasturchi "bola faqat props o'zgarsa render bo'ladi" deb o'ylaydi — aslida ota render bo'lganda bola avtomatik render bo'ladi (React props'ni tekshirmaydi —memosiz). Demak bitta yuqoridagi state o'zgarsa, butun pastdagi daraxt render bo'lishi mumkin. Lekin ikkinchi muhim haqiqat: re-render o'z-o'zidan yomon emas — React render fazasi tez (Virtual DOM — 11.2: 2.1), va ko'p render hech qanday muammo bermaydi. Muammo faqat keraksiz qimmat render'lar (uzun ro'yxat, og'ir hisob — 2.2). Shuning uchun "har render'ni to'xtatish" maqsad emas; maqsad — qimmat render'larni topib, faqat ularni optimallashtirish.
2.2. Re-render ≠ DOM update (render vs commit)
IKKI XIL "ISH" (11.2: 2.2 — chuqurroq):
1. RENDER fazasi — komponent funksiyasi ishlaydi → yangi Virtual DOM (ARZON)
React eski VDOM bilan solishtiradi (diffing/reconciliation)
2. COMMIT fazasi — FAQAT haqiqatan o'zgargan qism DOM'ga yoziladi (QIMMAT — 11.1: 2.7)
┌────────────────────────────────────────────────────────────┐
│ Re-render (funksiya ishlaydi + VDOM diffing): ARZON │
│ DOM update (haqiqiy DOM o'zgarishi — reflow/repaint): QIMMAT │
│ → ko'p re-render ≠ ko'p DOM update (React faqat farqni yozadi)│
└────────────────────────────────────────────────────────────┘
Misol: komponent 100 marta render bo'ldi, lekin natija (JSX) bir xil
→ React DOM'ni UMUMAN o'zgartirmaydi (diffing — farq yo'q → commit yo'q)
❗ "Re-render" — komponent funksiyasini qayta chaqirish (arzon); DOM update — boshqa
❗ Optimizatsiya 2 darajada: (a) qimmat RENDER'ni kamaytirish (memo); (b) DOM update React'daRe-render ≠ DOM update — eng muhim, lekin eng ko'p chalkashtiriladigan farq (11.2: 2.2 chuqurroq). React ikki fazada ishlaydi: render fazasi (komponent funksiyasi ishlaydi → yangi Virtual DOM hosil bo'ladi → eski bilan solishtiriladi — arzon, JS obyektlar bilan ishlash) va commit fazasi (faqat haqiqatan o'zgargan qism haqiqiy DOM'ga yoziladi — qimmat, reflow/repaint — 11.1: 2.7). Bu shuni anglatadi: komponent 100 marta re-render bo'lsa ham, agar natija (JSX) bir xil bo'lsa, React haqiqiy DOM'ni umuman o'zgartirmaydi (diffing farq topmaydi → commit yo'q). Ikki muhim xulosa: (1) "re-render" — bu komponent funksiyasini qayta chaqirish (arzon hisob), DOM'ni yangilash emas — shuning uchun "ko'p re-render" o'z-o'zidan falokat emas; (2) optimizatsiya ikki darajada bo'ladi — (a) qimmat renderni kamaytirish (
memo/useMemo— render fazasi yukini kamaytiradi), (b) DOM updateni React allaqachon minimallashtiradi (Virtual DOM). Bu farqni tushunish — "nima optimallashtirilyapti?" degan savolga to'g'ri javob berishning va keraksiz optimizatsiyadan qochishning kaliti.
2.3. Muammoni topish — o'lcha (React DevTools Profiler)
OPTIMIZATSIYA 1-QADAMI: O'LCHASH (taxmin emas — dalilga asoslan)
REACT DEVTOOLS PROFILER (brauzer kengaytmasi — majburiy vosita):
1. "Profiler" tab → yozib olish (record) → ilova bilan ishlash → to'xtatish
2. Ko'rsatadi: HAR komponent necha marta render bo'ldi, QANCHA vaqt oldi
3. "Flamegraph" — qaysi komponent eng qimmat (vaqt/render)
4. "Ranked" — eng sekin komponentlar tartiblangan
"HIGHLIGHT UPDATES" (Settings → render bo'lgan komponentni RANGLAYDI):
→ ekranda biror joyni o'zgartirsangiz, KERAKSIZ ranglangan joylar = ortiqcha render
CHROME PERFORMANCE / Lighthouse — umumiy (yuklanish, LCP, bundle — 11.8, 13.8)
┌────────────────────────────────────────────────────────────┐
│ "Sekin tuyuldi" → Profiler bilan O'LCHA → ANIQ muammoni top │
│ → faqat O'SHA joyni optimallashtir (dalilga asoslan) │
└────────────────────────────────────────────────────────────┘
❗ Profiler'siz optimizatsiya = ko'r-ko'rona (foydasiz memo, vaqt isrof)
❗ Avval o'lcha → muammoni aniqla → keyin tuzat (11.6: 2.13)Muammoni topish — o'lcha — performance optimizatsiyasining majburiy birinchi qadami. React DevTools Profiler (Chrome/Firefox brauzer kengaytmasi) — bu mavzuning eng muhim vositasi: "Profiler" tab'ida yozib olishni boshlaysiz (record), ilova bilan ishlaysiz (tugma bosasiz, yozasiz), to'xtatasiz — va u har komponent necha marta render bo'lganini va qancha vaqt olganini aniq ko'rsatadi. "Flamegraph" qaysi komponent eng qimmatligini, "Ranked" eng sekin komponentlarni tartiblangan ko'rsatadi. "Highlight updates" (Profiler sozlamalarida) — render bo'lgan komponentlarni ekranda ranglaydi: bir joyni o'zgartirganingda keraksiz ranglangan (boshqa) joylar = ortiqcha re-render'lar (vizual diagnostika). Umumiy yuklanish/bundle uchun Chrome Performance va Lighthouse (11.8, 13.8). Ikki tamoyil: (1) Profiler'siz optimizatsiya — ko'r-ko'rona (foydasiz
memoqo'shasiz, vaqt isrof qilasiz, ba'zan sekinlashtirasiz); (2) jarayon doim bir xil: "sekin tuyuldi" → Profiler bilan o'lcha → aniq muammoni top → faqat o'sha joyni optimallashtir (dalilga asoslan — 11.6: 2.13). O'lchash — senior performance ishining poydevori.
2.4. Re-render sabablari va yechimlari
KENG RE-RENDER SABABLARI (Profiler topsa — quyidagilardan biri):
1. OTA re-render → bola ham (props o'zgarmagan) — 2.1
→ yechim: React.memo (bola props bir xil bo'lsa render qilmasin — 2.6)
→ yoki state'ni pastga tushir (colocation — 2.5), children trick 2.8-bob
2. Yangi OBYEKT/FUNKSIYA props (har render yangi havola — 11.6: 2.9)
→ yechim: useMemo (obyekt), useCallback (funksiya) — 2.7
→ yoki inline'ni tashqariga chiqar 2.10-bob
3. CONTEXT qiymati o'zgardi → barcha consumer (11.5: 2.11)
→ yechim: context'ni bo'l (split), value'ni memo 2.9-bob
4. State JUDA YUQORIDA (kichik o'zgarish katta shoxni render qiladi)
→ yechim: state'ni ishlatadigan joyga yaqinlashtir (colocation — 2.5)
5. QIMMAT HISOB har render'da (filter/sort katta massiv)
→ yechim: useMemo (natijani keshla — 11.6: 2.8)
6. UZUN RO'YXAT (1000+ element — hammasi render/DOM'da)
→ yechim: virtualization (faqat ko'rinadigani — 2.11)
❗ Har muammoning O'Z yechimi bor → avval Profiler bilan QAYSI ekanini aniqlaRe-render sabablari va yechimlari — Profiler muammo topgach, u quyidagi sabablardan biri bo'ladi (har biri o'z yechimiga ega). (1) Ota re-render → bola ham (props o'zgarmagan — 2.1): yechim —
React.memo2.6-bob, yoki state'ni pastga tushirish 2.5-bob, yokichildrentrick 2.8-bob. (2) Yangi obyekt/funksiya props (har render yangi havola — 11.6: 2.9): yechim —useMemo/useCallback2.7-bob yoki inline'ni tashqariga chiqarish 2.10-bob. (3) Context qiymati o'zgardi → barcha consumer (11.5: 2.11): yechim — context'ni bo'lish (split), value'ni memo qilish 2.9-bob. (4) State juda yuqorida (kichik o'zgarish katta shoxni render qiladi): yechim — state'ni ishlatadigan joyga yaqinlashtirish (colocation — 2.5). (5) Qimmat hisob har render'da (katta massiv filter/sort): yechim —useMemo(11.6: 2.8). (6) Uzun ro'yxat (1000+ element): yechim — virtualization 2.11-bob. Asosiy nuqta: har muammoning o'z yechimi bor —memohamma narsaning davosi emas. Shuning uchun avval Profiler bilan qaysi sabab ekanini aniqlab, keyin mos yechimni qo'llaysiz. Bu — tashxis-asosli (diagnostic) yondashuv.
2.5. State colocation — state'ni pastga tushir
STATE COLOCATION — state'ni uni ISHLATADIGAN joyga eng yaqin qo'yish (pastga tushir):
❌ State juda YUQORIDA (kichik input katta shoxni render qiladi):
function App() {
const [search, setSearch] = useState(""); // faqat SearchBox ishlatadi
return (
<>
<SearchBox value={search} onChange={setSearch} />
<HugeExpensiveList /> {/* search o'zgarsa BU HAM render (bekorga — sekin!) */}
</>
);
}
✅ State'ni PASTGA tushir (faqat kerakli komponentda):
function App() {
return (
<>
<SearchBox /> {/* search shu ICHIDA (App render bo'lmaydi) */}
<HugeExpensiveList /> {/* search o'zgarsa BU render BO'LMAYDI */}
</>
);
}
function SearchBox() {
const [search, setSearch] = useState(""); // shu yerda — faqat SearchBox render
return <input value={search} onChange={e => setSearch(e.target.value)} />;
}
❗ State'ni keraksiz YUQORI ko'tarma (lifting state up — 11.4: 2.14 — faqat ULASHISH kerak bo'lsa)
❗ Colocation — eng oddiy, eng kuchli optimizatsiya (memo'dan OLDIN buni o'yla)State colocation — state'ni uni ishlatadigan komponentga eng yaqin (eng past) joyga qo'yish. Bu — eng oddiy va ko'pincha eng kuchli optimizatsiya, lekin ko'p e'tibordan chetda qoladi. Muammo: agar state juda yuqorida bo'lsa (
App'da), uni o'zgartirish butun pastdagi daraxtni re-render qiladi — masalansearchstateApp'da bo'lsa, har harf yozilgandaHugeExpensiveListham bekorga render bo'ladi (sekin). Yechim — state'ni faqat uni ishlatadigan komponentga tushirish:searchniSearchBoxichiga ko'chirsangiz, har harfda faqatSearchBoxrender bo'ladi,HugeExpensiveListtegmaydi (chunkiAppendi render bo'lmaydi). Ikki tamoyil: (1) state'ni keraksiz yuqori ko'tarma — lifting state up (11.4: 2.14) faqat bir necha komponent state'ni ulashishi kerak bo'lganda qilinadi; agar faqat bitta komponent ishlatsa, state o'sha komponentda bo'lsin (yaqin tut); (2) colocation —memo'dan oldin o'ylash kerak bo'lgan optimizatsiya (ko'pinchamemoqo'shish o'rniga state'ni to'g'ri joyga qo'yish muammoni butunlay hal qiladi). Bu — "to'g'ri arxitektura > optimizatsiya plaster" tamoyili.
2.6. React.memo chuqur — props taqqoslash
React.memo — bola props O'ZGARMASA, re-render qilMASLIK (11.6: 2.12 — chuqurroq):
const ProductCard = React.memo(function ProductCard({ product, onAdd }) {
return <div>{product.name} <button onClick={() => onAdd(product.id)}>+</button></div>;
});
// → ota render bo'lsa ham, product/onAdd o'zgarmagan bo'lsa — ProductCard render BO'LMAYDI
QANDAY TAQQOSLAYDI: props'ni YUZAKI (shallow) === bilan (11.6: 2.9):
- primitiv (string/number/bool): qiymat bo'yicha (oson)
- obyekt/massiv/funksiya: HAVOLA bo'yicha (yangi havola = "o'zgargan" → render!)
→ SHUNING UCHUN obyekt/funksiya props useMemo/useCallback bilan barqaror (2.7, 11.6: 2.12)
CUSTOM TAQQOSLASH (2-argument — kam kerak):
React.memo(Component, (prev, next) => prev.id === next.id); // faqat id bo'yicha (true=render YO'Q)
❗ React.memo — har komponentga qo'shma (faqat: tez-tez render + props kam o'zgaradi + qimmat)
❗ React.memo + useMemo + useCallback — UCHALASI birga (biri yolg'iz foydasiz — 2.7, 11.6: 2.12)
React.memochuqur — komponentni o'rab, props o'zgarmasa re-render qilmaydigan HOC (11.6: 2.12 chuqurroq).React.memo(ProductCard)— ota render bo'lsa ham, agarproduct/onAddprops o'zgarmagan bo'lsa,ProductCardrender bo'lmaydi (oldingi natija ishlatiladi). Qanday taqqoslaydi: props'ni yuzaki (shallow)===bilan solishtiradi (11.6: 2.9) — primitiv (string/number/bool) qiymat bo'yicha (oson), obyekt/massiv/funksiya esa havola bo'yicha (yangi havola = "o'zgargan" deb hisoblaydi → render qiladi). Shuning uchun obyekt/funksiya props'lariniuseMemo/useCallbackbilan barqaror ushlash kerak 2.7-bob — aks holdaReact.memofoydasiz bo'ladi (har render yangi havola → memo har doim "o'zgardi" deydi). Custom taqqoslash (ikkinchi argument — kam kerak):React.memo(C, (prev, next) => prev.id === next.id)— faqatidbo'yicha solishtirish (trueqaytsa render yo'q). Ikki muhim qoida: (1)React.memoni har komponentga qo'shma — faqat tez-tez render bo'ladigan + props kam o'zgaradigan + qimmat komponentga 2.13-bob; (2)React.memo+useMemo+useCallbackuchalasi birga ishlaydi (biri yolg'iz ko'pincha foydasiz — 11.6: 2.12). Bu — eng ko'p ishlatiladigan, lekin eng ko'p noto'g'ri ishlatiladigan optimizatsiya.
2.7. useMemo/useCallback — performance kontekstida
PERFORMANCE'DA useMemo/useCallback IKKI vazifa (11.6 takror, perf fokus):
1. QIMMAT HISOBni keshlash (render fazasi yukini kamaytirish — 11.6: 2.8):
const sorted = useMemo(() => bigList.sort(...), [bigList]); // har render emas — kerak bo'lganda
2. REFERENTIAL barqarorlik (React.memo'li bola re-render'ini to'xtatish — 11.6: 2.9):
const handleClick = useCallback(() => {...}, []); // barqaror funksiya
const config = useMemo(() => ({ theme }), [theme]); // barqaror obyekt
<MemoChild onClick={handleClick} config={config} /> // endi memo ishlaydi 2.6-bob
QACHON KERAK (perf):
✓ React.memo'li bolaga obyekt/funksiya prop (barqarorlik — 2.6)
✓ useEffect/useMemo deps'da obyekt/funksiya (cheksiz/keraksiz — 11.5: 2.9)
✓ Haqiqatan qimmat hisob (Profiler tasdiqladi)
QACHON KERAK EMAS (perf zarari):
✗ Arzon hisob, oddiy funksiya, memo'siz bola (ortiqcha — 11.6: 2.13)
❗ useMemo/useCallback — referential barqarorlik ASOSIY (React.memo bilan birga)
❗ Yolg'iz useCallback (memo'siz bolaga) — FOYDASIZ (faqat memo bilan ma'noli — 2.6)
useMemo/useCallbackperformance kontekstida — 11.6'ni performance rakursidan takrorlaydi (ikki vazifa). (1) Qimmat hisobni keshlash — render fazasi yukini kamaytirish (useMemo(() => bigList.sort(...), [bigList])— har render'da emas, faqatbigListo'zgarganda — 11.6: 2.8). (2) Referential barqarorlik —React.memo'li bolaning re-render'ini to'xtatish: obyekt prop'niuseMemo, funksiya prop'niuseCallbackbilan barqaror ushlaysiz, shundaReact.memohaqiqatan ishlaydi (2.6, 11.6: 2.9). Qachon kerak (perf):React.memo'li bolaga obyekt/funksiya prop;useEffect/useMemodeps'ida obyekt/funksiya (cheksiz/keraksiz effekt'dan saqlaydi — 11.5: 2.9); haqiqatan qimmat hisob (Profiler tasdiqlagan). Qachon kerak emas (perf zarari): arzon hisob, oddiy funksiya,memosiz bolaga beriladigan prop (ortiqcha — 11.6: 2.13). Eng muhim:useCallback/useMemoning asosiy performance vazifasi — referential barqarorlik (React.memobilan birga); yolg'izuseCallback(memo'siz bolaga beriladigan funksiya) — foydasiz (faqatReact.memobilan ma'noli — 2.6). Bu uchligi (memo + useMemo + useCallback) doim birga ishlatiladi.
2.8. children prop fokusi — re-render'ni to'xtatish
CHILDREN TRICK — children sifatida uzatilgan JSX OTA render'dan TA'SIRLANMAYDI:
❌ State o'zgarsa butun ichka render bo'ladi:
function App() {
const [count, setCount] = useState(0);
return (
<div onClick={() => setCount(count + 1)}>
<ExpensiveTree /> {/* count o'zgarsa BU HAM render (bekorga) */}
</div>
);
}
✅ ExpensiveTree'ni children sifatida uzat (tashqarida yaratiladi — render'lanmaydi):
function App() {
return (
<Counter>
<ExpensiveTree /> {/* children — Counter render bo'lsa HAM qayta yaralmaydi */}
</Counter>
);
}
function Counter({ children }) {
const [count, setCount] = useState(0);
return <div onClick={() => setCount(count + 1)}>{children}</div>; // children o'zgarmaydi
}
❗ children — ota komponentda (App) yaratildi → Counter state o'zgarsa children QAYTA yaralmaydi
❗ "Lifting content up" — memo'siz re-render'ni to'xtatishning nafis usuli (React'ning tabiati)
childrenprop trick — re-render'nimemosiz to'xtatishning nafis usuli. G'oya:childrensifatida uzatilgan JSX ota komponentda (yuqorida) yaratiladi, shuning uchun state state-tutuvchi komponent re-render bo'lganda qayta yaralmaydi (havolasi bir xil qoladi). Misol: agarExpensiveTreecountstate-tutuvchidivichida bevosita bo'lsa, harcounto'zgargandaExpensiveTreeham bekorga render bo'ladi. LekinExpensiveTreeni<Counter>gachildrensifatida uzatsangiz (<Counter><ExpensiveTree /></Counter>),ExpensiveTreeAppda yaratiladi (yuqorida), vaCountero'zcount'ini o'zgartirgandachildren(ya'niExpensiveTree) qayta yaralmaydi — uning havolasi o'zgarmaydi, React uni render qilmaydi. Bu naqsh "lifting content up" deb ataladi. Ikki nuqta: (1) bu — React'ning tabiiy xulqi (referential barqarorlik —childrenyuqorida yaralib, pastga o'zgarmas havola sifatida o'tadi),memo'siz ishlaydi; (2) state'ni tashqi holatga bog'liq bo'lmagan og'ir kontentdan ajratishning toza usuli. Bu — ko'p e'tibordan chetda qoladigan, lekin juda kuchli optimizatsiya naqshi.
2.9. Context optimizatsiyasi — bo'lish va value memo
CONTEXT MUAMMOSI: Provider value o'zgarsa — BARCHA consumer re-render (11.5: 2.11)
❌ Bitta katta context + har render yangi value obyekti:
<AppContext.Provider value={{ user, theme, cart, setCart }}> {/* har render YANGI obyekt */}
// → user/theme/cart'dan bittasi o'zgarsa — HAMMASINI ishlatgan consumer render
YECHIM 1 — value'ni MEMO qil (har render yangi obyekt bo'lmasin — 11.6: 2.9):
const value = useMemo(() => ({ user, login, logout }), [user]); // barqaror
<AuthContext.Provider value={value}>
YECHIM 2 — Context'ni BO'L (ajrat — tez-tez/kam o'zgaradigan alohida):
<AuthContext.Provider value={authValue}> {/* kam o'zgaradi */}
<ThemeContext.Provider value={themeValue}> {/* alohida */}
<CartContext.Provider value={cartValue}> {/* tez o'zgaradi — alohida */}
// → cart o'zgarsa faqat CartContext consumer render (auth/theme tegmaydi)
┌────────────────────────────────────────────────────────────┐
│ value'ni memo (barqaror) + context'ni bo'l (mas'uliyat) = │
│ keraksiz consumer re-render'ni to'xtatadi │
└────────────────────────────────────────────────────────────┘
❗ Katta/tez o'zgaradigan global state → Context emas, Redux/Zustand (selektor bilan — 12.2, 12.5)
❗ Context — kam o'zgaradigan (theme/auth) uchun ideal; tez-tez o'zgaradiganga ehtiyotContext optimizatsiyasi — Context'ning performance tuzog'ini hal qiladi. Muammo: Provider'ning
value'si o'zgarganda, o'sha Context'ni ishlatgan barcha consumer re-render bo'ladi (11.5: 2.11). Ikki keng xato: bitta katta context ({ user, theme, cart }) — bittasi o'zgarsa hammasini ishlatgan consumer render; va har render'da yangivalueobyekti (referential — 11.6: 2.9). Yechim 1 —valueniuseMemobilan barqaror ushlash (useMemo(() => ({ user, login }), [user])— har render yangi obyekt bo'lmasin). Yechim 2 — Context'ni bo'lish (ajratish): tez-tez o'zgaradigan (cart) va kam o'zgaradigan (auth, theme) ma'lumotlarni alohida Context'larga ajratasiz — shundacarto'zgarganda faqatCartContextconsumer'lari render bo'ladi (auth/themetegmaydi). Ikki strategik nuqta: (1)valuememo + context split = keraksiz consumer re-render'ni to'xtatadi; (2) lekin agar global state katta va tez-tez o'zgaradigan bo'lsa (real-time savat, jonli ma'lumot), Context o'rniga Redux/Zustand (12.2, 12.5) — ular selektor bilan ishlaydi (faqat kerakli qismni ishlatgan komponent render bo'ladi — Context buni qila olmaydi). Context — kam o'zgaradigan ma'lumot uchun ideal; tez-tez o'zgaradiganga ehtiyot bo'ling.
2.10. Inline obyekt/funksiyadan qochish va key bilan reset
INLINE OBYEKT/FUNKSIYA — JSX'da to'g'ridan yaratish (har render yangi havola — 11.6: 2.9):
❌ <MemoChild style={{ color: "red" }} onClick={() => doX()} />
// └─ har render YANGI obyekt └─ har render YANGI funksiya
// → MemoChild memo BO'LSA ham — har doim render (yangi havola — 2.6)
✅ Tashqariga chiqar (barqaror havola):
const style = useMemo(() => ({ color: "red" }), []);
const handleClick = useCallback(() => doX(), []);
<MemoChild style={style} onClick={handleClick} />
KEY bilan STATE RESET (boshqa optimizatsiya/naqsh — komponentni "yangidan" boshlash):
<Profile key={userId} /> // userId o'zgarsa — Profile BUTUNLAY yangi (state tozalanadi)
// → eski state'ni qo'lda tozalash (useEffect) o'rniga — key bilan komponentni almashtirish
┌────────────────────────────────────────────────────────────┐
│ Inline {} / () => : memo'li bolada zararli (yangi havola) │
│ key={id}: id o'zgarsa komponent state'ini RESET (tabiiy) │
└────────────────────────────────────────────────────────────┘
❗ Memo'li bolaga inline obyekt/funksiya BERMANG (memo'ni buzadi — 2.6)
❗ key o'zgarsa React komponentni o'chirib-qayta yaratadi (state reset — useEffect'siz)Inline obyekt/funksiyadan qochish va key bilan reset — ikki amaliy naqsh. Inline'dan qochish: JSX'da to'g'ridan obyekt (
style={{...}}) yoki funksiya (onClick={() => ...}) yozsangiz, har render'da yangi havola yaratiladi (11.6: 2.9) — buReact.memo'li bolaga berilsa, memo buziladi (bola har doim "yangi prop" ko'radi → render). Yechim — ularniuseMemo/useCallbackbilan tashqariga chiqarish (barqaror havola). Eslatma: memo'siz oddiy bolada inline yaxshi (oddiy va tez), faqatmemo'li bola bilan muammo.keybilan state reset — boshqa foydali naqsh: komponentgakeyberib, u o'zgarganda React komponentni butunlay yangi (o'chirib-qayta yaratadi) qiladi, shuning uchun ichki state tozalanadi (<Profile key={userId} />—userIdo'zgarganda Profile yangidan boshlanadi). Bu — eski state'niuseEffectbilan qo'lda tozalashdan tozaroq usul (React'ning tabiiy mexanizmidan foydalanadi). Ikki nuqta: (1) memo'li bolaga inline obyekt/funksiya bermang (memo'ni bekor qiladi — 2.6); (2)keyo'zgarsa React komponentni reset qiladi — bu ham performance, ham toza state boshqaruvi (foydalanuvchi/element almashganda formani tozalash uchun ideal).
2.11. List virtualization — uzun ro'yxatlar
MUAMMO: 10 000 elementli ro'yxat — hammasini render + DOM'ga qo'yish (sekin, ko'p xotira)
VIRTUALIZATION (windowing) — faqat EKRANDA KO'RINADIGANni render (10-20 element):
→ 10 000 element bor, lekin DOM'da faqat ~20 (ko'rinadigan oyna) — skroll'da almashadi
┌────────────────────────────────────────────────────────────┐
│ Oddiy: 10000 <li> DOM'da (sekin render, ko'p xotira, lag) │
│ Virtual: ~20 <li> DOM'da (ko'rinadigan) — skroll'da yangilan-│
│ adi (10000 ta bo'lsa ham TEZ) │
└────────────────────────────────────────────────────────────┘
KUTUBXONALAR (2026):
- @tanstack/react-virtual (zamonaviy, moslashuvchan — tavsiya)
- react-window (oddiy, yengil)
- react-virtuoso (boy imkoniyatli)
import { useVirtualizer } from "@tanstack/react-virtual";
// → faqat ko'rinadigan elementlar render bo'ladi (virtualItems)
❗ Virtualization — 100+ (ayniqsa 1000+) elementli ro'yxat uchun MAJBURIY (chat, jadval, feed)
❗ Kichik ro'yxat (10-50) — kerak emas (oddiy map yetadi — ortiqcha murakkablik)List virtualization — uzun ro'yxatlar muammosini hal qiladi. Muammo: 10 000 elementli ro'yxatni oddiy
.map()bilan render qilsangiz, hammasi (10 000 ta<li>) Virtual DOM'da hisoblanadi va haqiqiy DOM'ga qo'yiladi — bu sekin render, ko'p xotira, va skrollda lag (kechikish) keltiradi. Virtualization (yoki "windowing") — faqat ekranda ko'rinadigan elementlarni render qilish (10 000 ta bo'lsa ham DOM'da faqat ~20 ta — ko'rinadigan "oyna"); foydalanuvchi skroll qilganda, ko'rinadigan elementlar almashadi (eski yo'qoladi, yangi paydo bo'ladi). Natija — ro'yxat 10 000 ta bo'lsa ham tez ishlaydi (DOM'da doim ~20 element). Kutubxonalar (2026):@tanstack/react-virtual(zamonaviy, moslashuvchan — tavsiya),react-window(oddiy, yengil),react-virtuoso(boy imkoniyatli).useVirtualizerhook'i ko'rinadigan elementlarni hisoblaydi. Ikki nuqta: (1) virtualization — 100+ (ayniqsa 1000+) elementli ro'yxatlar uchun majburiy (chat tarixi, katta jadval, cheksiz feed, mahsulotlar); (2) kichik ro'yxat (10-50 element) uchun kerak emas — oddiy.map()yetadi (virtualization ortiqcha murakkablik keltiradi). Bu — katta ma'lumotli UI'ning eng muhim performance texnikasi.
2.12. Debounce va throttle — qimmat hodisalar
MUAMMO: tez-tez ishlaydigan hodisa (yozish, skroll, resize) qimmat ishni KO'P chaqiradi
→ har keystroke API so'rovi / har skroll og'ir hisob = sekin, isrof
DEBOUNCE — hodisa TO'XTAGUNCHA kut, keyin BIR marta ishla (11.7 useDebounce):
yozish: ...t...te...tel...telef → 400ms to'xtadi → BIR so'rov "telefon"
→ har harfda emas, yozish tugagach (qidiruv uchun ideal)
THROTTLE — har N ms'da KO'PIDA BIR marta ishla (muntazam cheklash):
skroll: har pikselda emas, har 100ms'da bir marta (skroll/resize uchun)
┌──────────────┬─────────────────────────────────────────────┐
│ Debounce │ to'xtaguncha kut → 1 marta (qidiruv, autosave) │
│ Throttle │ har N ms'da 1 marta (skroll, resize, mouse) │
└──────────────┴─────────────────────────────────────────────┘
useDebounce 11.7-bob yoki lodash debounce/throttle; React 19: useDeferredValue 2.13-bob
❗ Debounce — "tugagach" (qidiruv); throttle — "muntazam cheklash" (skroll)
❗ Tez-tez ishlaydigan qimmat hodisani CHEKLA (har eventda emas)Debounce va throttle — tez-tez ishlaydigan hodisalardagi qimmat ishni cheklaydi. Muammo: yozish (
onChange), skroll (onScroll), resize — bular soniyada o'nlab-yuzlab marta ishlaydi; agar har birida qimmat ish (API so'rovi, og'ir hisob) qilsangiz — sekin va isrof. Debounce — hodisa to'xtaguncha kutib, keyin bir marta ishlaydi (11.7useDebounce): masalan qidiruv inputida foydalanuvchi yozishni tugatib 400ms kutgach bitta so'rov yuboriladi (har harfda emas). Throttle — har N millisekundda ko'pida bir marta ishlaydi (muntazam cheklash): masalan skrollda har pikselda emas, har 100ms'da bir marta hisob. Farq: debounce "tugagach bir marta" (qidiruv, autosave), throttle "har N ms'da bir marta" (skroll, resize, mouse harakati). Ikki nuqta: (1) to'g'ri tanlov — qidiruv/autosave uchun debounce (foydalanuvchi to'xtaganda), skroll/resize uchun throttle (muntazam, lekin cheklangan); (2) amalga oshirish —useDebouncecustom hook 11.7-bob,lodashdebounce/throttle, yoki React 19'ninguseDeferredValue2.13-bob. Bu texnika tez-tez ishlaydigan hodisalar bo'lgan UI'larda (jonli qidiruv, infinite scroll, sudraluvchi panellar) hal qiluvchi.
2.13. Concurrent: useTransition va useDeferredValue
REACT 18+ CONCURRENT — UI'ni RESPONSIVE ushlash (qimmat yangilanish bloklamasin):
useTransition — yangilanishni "shoshilmas" (non-urgent) deb belgilash:
const [isPending, startTransition] = useTransition();
function handleChange(e) {
setQuery(e.target.value); // SHOSHILINCH (input darrov yangilansin)
startTransition(() => {
setResults(filterBig(e.target.value)); // SHOSHILMAS (og'ir — input'ni bloklamasin)
});
}
// → input darrov yoziladi (responsive); og'ir filtr fonda (UI qotmaydi)
{isPending && <Spinner />} // o'tish davom etayotganini ko'rsatish
useDeferredValue — qiymatning "kechiktirilgan" nusxasi (og'ir UI uchun):
const deferredQuery = useDeferredValue(query); // query darrov; deferredQuery kechikadi
const list = useMemo(() => filterBig(deferredQuery), [deferredQuery]); // og'ir ro'yxat kechikadi
// → input darrov; ro'yxat biroz orqada (lekin UI qotmaydi)
┌────────────────────────────────────────────────────────────┐
│ useTransition: yangilanishni non-urgent qil (startTransition) │
│ useDeferredValue: qiymatni kechiktir (og'ir UI input'ni qotirmasin)│
└────────────────────────────────────────────────────────────┘
❗ Concurrent — qimmat yangilanish paytida UI'ni RESPONSIVE ushlaydi (input qotmaydi)
❗ Katta ro'yxat + jonli filtr/qidiruv — useDeferredValue (yoki debounce — 2.12) idealConcurrent (useTransition, useDeferredValue) — React 18+ ning UI'ni responsive ushlaydigan imkoniyatlari. G'oya: ba'zi yangilanishlar shoshilinch (input darrov yangilanishi kerak — foydalanuvchi yozyapti), ba'zilari shoshilmas (og'ir ro'yxat filtri biroz kechiksa ham mayli) — bularni ajratish UI qotishining oldini oladi.
useTransition— yangilanishni "shoshilmas" deb belgilaydi:startTransition(() => setResults(filterBig(...)))— input darrov yoziladi (setQueryshoshilinch), og'ir filtr esa fonda (input'ni bloklamaydi);isPendingo'tish davom etayotganini ko'rsatadi (spinner).useDeferredValue— qiymatning "kechiktirilgan" nusxasini beradi:const deferredQuery = useDeferredValue(query)—querydarrov o'zgaradi (input responsive),deferredQuerybiroz orqada keladi, og'ir ro'yxat undan hisoblanadi (useMemo(() => filterBig(deferredQuery), [deferredQuery])) — ro'yxat biroz kechikadi, lekin input qotmaydi. Ikki nuqta: (1) concurrent vositalar — qimmat yangilanish UI'ni bloklamasligi uchun (katta ro'yxat + jonli qidiruv/filtr — input qotmasin); (2)useDeferredValuedebounce'ga 2.12-bob o'xshaydi, lekin React'ning ichki mexanizmi (qiymatni "tashlash" o'rniga kechiktirish) — ko'pincha jonli filtr uchun ideal. Bular — modern React'ning silliq UX'ining kaliti.
2.14. Bundle, rasm, web worker va Web Vitals (yuklanish + og'ir ish)
RENDER PERFORMANCE (memo, re-render) — YUGURISH vaqti; lekin YANA IKKI o'lcham bor:
(A) YUKLANISH performance (bundle, rasm — 11.8) — sahifa qancha tez ochiladi
(B) OG'IR HISOB (web worker) — asosiy oqim (main thread) bloklanmasin
── (A) BUNDLE OPTIMIZATSIYA (yuklanadigan JS hajmini kamaytirish — 11.8: cross-ref):
- TREE-SHAKING: ishlatilmagan kod bundle'ga TUSHMAYDI (named import — { x })
→ import { debounce } from "lodash-es"; // ✅ faqat debounce (tree-shakable)
→ import _ from "lodash"; // ❌ butun kutubxona (og'ir)
- CODE SPLITTING / DYNAMIC IMPORT: lazy(() => import(...)) — kerak bo'lganda yukla 11.8-bob
- ANALYZE: bundle'ni o'lcha (rollup-plugin-visualizer / source-map-explorer) → nima og'ir?
── (B) RASM OPTIMIZATSIYA (ko'pincha eng katta yuk — LCP'ga bevosita ta'sir):
- LAZY LOADING: <img loading="lazy" /> — ko'rinmagan rasm keyin yuklanadi
- RESPONSIVE: srcSet + sizes — ekranga mos o'lcham (mobilga kichik rasm)
- FORMAT: WebP/AVIF (JPEG/PNG'dan yengil); width/height ber (CLS — layout siljimasin)
── (B) WEB WORKER (og'ir CPU ishi — main thread'ni QOTIRMASLIK):
→ useMemo render fazasini keshlaydi, LEKIN o'ta og'ir hisob (katta massiv, parsing,
kript, tasvir) main thread'ni baribir bloklaydi → Web Worker'ga OFFLOAD qil
→ worker alohida oqimda ishlaydi → UI qotmaydi (natijani postMessage bilan qaytaradi)
── WEB VITALS (foydalanuvchi sezadigan real o'lchov — 13.8 cross-ref):
┌──────┬──────────────────────────────────────────────────────────┐
│ LCP │ eng katta element ko'rinishi (yuklanish) — rasm/bundle │
│ INP │ bosishga javob tezligi (interaktivlik) — og'ir render/JS │
│ CLS │ layout siljishi (rasm/font o'lchamsiz) — width/height ber │
└──────┴──────────────────────────────────────────────────────────┘
→ web-vitals kutubxonasi: onLCP/onINP/onCLS — real foydalanuvchi ma'lumotini o'lcha
❗ Render optimizatsiya (memo) — YUGURISH; bundle/rasm — YUKLANISH; ikkalasi ham muhim
❗ Web Vitals — "his" emas, REAL o'lchov (Lighthouse laboratoriya; web-vitals dala/RUM)Bundle, rasm, web worker va Web Vitals — shu paytgacha bob render (yugurish vaqti) performance'iga qaratildi (
memo, re-render), lekin ilova tezligining yana ikki katta o'lchami bor: yuklanish (sahifa qancha tez ochiladi — bundle, rasm) va og'ir hisob (main thread bloklanmasin — web worker). (A) Bundle optimizatsiya (11.8 chuqurroq): (1) tree-shaking — ishlatilmagan kod bundle'ga tushmaydi (named import —import { debounce } from "lodash-es"faqat kerakli qismni oladi;import _ from "lodash"butun kutubxonani); (2) dynamic import / code splitting —lazy(() => import(...))bilan kod kerak bo'lganda yuklanadi 11.8-bob; (3) analyze — bundle'ni o'lchash (rollup-plugin-visualizer,source-map-explorer) bilan qaysi paket og'irligini topasiz — bu ham "o'lchang, taxmin qilmang". (A) Rasm optimizatsiya — rasmlar ko'pincha sahifaning eng og'ir yuki va LCP'ga bevosita ta'sir qiladi:loading="lazy"(ko'rinmagan rasm keyin yuklanadi),srcSet+sizes(ekranga mos o'lcham — mobilga kichik rasm), zamonaviy format (WebP/AVIF — JPEG/PNG'dan yengil), va rasmgawidth/heightberish (CLS — layout siljimasin). (B) Web worker —useMemorender fazasidagi qimmat hisobni keshlaydi, lekin o'ta og'ir ish (millionlab elementli massiv, katta JSON parsing, kriptografiya, tasvir qayta ishlash) baribir main thread'ni bloklaydi (UI qotadi); bunday ishni Web Worker'ga o'tkazasiz — u alohida oqimda ishlaydi, natijanipostMessagebilan qaytaradi, UI esa silliq qoladi. Web Vitals (13.8 chuqurroq) — foydalanuvchi haqiqatan sezadigan uch o'lchov: LCP (eng katta element ko'rinishi — yuklanish, rasm/bundle bilan bog'liq), INP (bosishga javob tezligi — interaktivlik, og'ir render/JS bilan bog'liq — bu bob), CLS (layout kutilmagan siljishi — rasm/font o'lchamsiz bo'lsa);web-vitalskutubxonasi (onLCP/onINP/onCLS) bularni real foydalanuvchida (dala/RUM) o'lchaydi. Ikki nuqta: (1) render optimizatsiya (memo — yugurish) va yuklanish optimizatsiya (bundle/rasm) — ikki alohida o'lcham, ikkalasi ham foydalanuvchi tajribasiga muhim; (2) Web Vitals — "menga sekin tuyuldi" emas, real o'lchov (Lighthouse — laboratoriya,web-vitals— dala) — bu bobning "o'lchang, taxmin qilmang" tamoyilining kengaygan ko'rinishi.
2.15. Suspense va SSR/streaming (yuklanish tajribasi)
SUSPENSE — komponent "tayyor bo'lguncha" fallback ko'rsatish (deklarativ kutish):
<Suspense fallback={<Spinner />}>
<LazyChart /> {/* lazy(() => import(...)) — yuklanguncha Spinner 11.8-bob */}
</Suspense>
→ lazy komponent yoki ma'lumot (framework bilan) yuklanayotganini nafis ko'rsatadi
SSR / STREAMING (server-side rendering — Next.js cross-ref, 15-QISM):
- SSR: server HTML'ni oldindan chiqaradi → foydalanuvchi tez KO'RADI (LCP yaxshi)
- STREAMING SSR: sahifani BO'LAKLAB yuboradi (<Suspense> chegaralari bo'yicha)
→ tayyor qism darrov, og'ir qism keyin oqib keladi (foydalanuvchi kutmaydi)
- RSC (React Server Components): ba'zi komponent SERVERda render (bundle'ga tushmaydi)
❗ SSR/streaming — YUKLANISH tajribasini yaxshilaydi (client render optimizatsiyasidan boshqa)
❗ Next.js/Remix (15-QISM) — bularni tayyor beradi; bu bob esa CLIENT render'iga qaratilganSuspense va SSR/streaming — yuklanish tajribasini yaxshilaydigan React imkoniyatlari (client render'idan boshqa o'lcham).
Suspense— komponent yoki uning ma'lumoti tayyor bo'lguncha fallback (masalan spinner) ko'rsatishning deklarativ usuli:<Suspense fallback={<Spinner/>}><LazyChart/></Suspense>—lazy(() => import(...))bilan yuklanadigan komponent 11.8-bob yoki (framework bilan) ma'lumot yuklanayotganini nafis boshqaradi (isLoadingstate'ni qo'lda ushlab turishdan tozaroq). SSR va streaming (Next.js — 15-QISM chuqurroq): (1) SSR (server-side rendering) — server HTML'ni oldindan chiqaradi, shuning uchun foydalanuvchi kontentni tez ko'radi (LCP yaxshilanadi, JS yuklanguncha ham sahifa ko'rinadi); (2) streaming SSR — sahifa<Suspense>chegaralari bo'yicha bo'laklab yuboriladi: tayyor qism darrov keladi, og'ir qism keyin "oqib" keladi (foydalanuvchi butun sahifani kutmaydi); (3) RSC (React Server Components) — ba'zi komponentlar serverda render bo'ladi va client bundle'iga umuman tushmaydi (bundle yengillashadi). Ikki nuqta: (1) SSR/streaming — yuklanish tajribasini yaxshilaydi (bu bobning client-side render optimizatsiyasidan alohida o'lcham); (2) bularni odatda framework (Next.js, Remix — 15-QISM) tayyor beradi — bu bob esa client render (re-render, memo) optimizatsiyasiga qaratilgan; ikkalasi birga to'liq tez ilovani beradi.
2.16. React Compiler va performance tafakkuri
REACT COMPILER (2024-2025, React 19) — memoizatsiyani AVTOMATIK qiladi (11.6: 2.14):
→ useMemo/useCallback/React.memo'ni qo'lda yozish KO'P holda kerak emas
→ compiler kodni tahlil qilib, keraksiz re-render'larni O'ZI to'xtatadi
LEKIN compiler ham QOIDALARga tayanadi (buzilsa yordam berolmaydi):
- Sof komponent (render paytida side effect yo'q — 11.2: 2.2)
- Rules of Hooks (11.5: 2.2)
- Immutability (state mutatsiya yo'q — 11.4: 2.7)
PERFORMANCE TAFAKKURI (eng muhim xulosa):
1. AVVAL TO'G'RI yoz (oddiy, ishlaydigan — optimizatsiyasiz)
2. MUAMMO bormi? — O'LCHA (Profiler — 2.3)
3. ANIQ muammoni top (qaysi komponent, qaysi sabab — 2.4)
4. MOS yechimni qo'lla (colocation/memo/virtual/defer — 2.5-2.13)
5. QAYTA o'lcha (foyda bo'ldimi?)
┌────────────────────────────────────────────────────────────┐
│ "Premature optimization is the root of all evil" │
│ → To'g'ri > Tez. O'lcha > Taxmin. Aniq > Hamma joyga. │
└────────────────────────────────────────────────────────────┘
❗ React Compiler bo'lsa ham — tushuncha SHART (debug, eski kod, nazorat)
❗ Eng katta xato — o'lchamasdan, hamma joyga memo (murakkab + foydasiz)React Compiler va performance tafakkuri (2.16) — bobning yakuniy, eng muhim xulosasi. React Compiler (React 19 bilan — 11.6: 2.14) memoizatsiyani avtomatik qiladi: kodni tahlil qilib, qaerda
useMemo/useCallback/React.memokerakligini o'zi aniqlaydi va keraksiz re-render'larni to'xtatadi — shuning uchun qo'lda memoizatsiya ko'p holda kerak bo'lmaydi. Lekin compiler ham qoidalarga tayanadi (sof komponent, Rules of Hooks, immutability — buzilsa yordam berolmaydi). Performance tafakkuri (5 qadam, butun bobning mohiyati): (1) avval to'g'ri yoz (oddiy, ishlaydigan, optimizatsiyasiz); (2) muammo bormi? — o'lcha (Profiler — 2.3); (3) aniq muammoni top (qaysi komponent, qaysi sabab — 2.4); (4) mos yechimni qo'lla (colocation, memo, virtualization, defer — 2.5-2.13); (5) qayta o'lcha (foyda bo'ldimi?). Ikki yakuniy tamoyil: (1) mashhur "premature optimization is the root of all evil" — to'g'ri > tez, o'lcha > taxmin, aniq > hamma joyga; (2) React Compiler bo'lsa ham, bu tushunchalar shart (xato tuzatish, eski kod, aniq nazorat). Eng katta xato — o'lchamasdan, hamma joygamemotiqishtirish (kod murakkablashadi, foyda yo'q). Senior dasturchi — tashxis qo'yib, aniq davo beradi.
3. Sintaksis — tez ma'lumotnoma
PROFILER 2.3-bob: React DevTools → Profiler → record → "Highlight updates"
React.memo 2.6-bob: const C = React.memo(Comp) | React.memo(Comp, (p,n) => p.id===n.id)
useMemo 2.7-bob: const x = useMemo(() => expensive(a), [a])
useCallback 2.7-bob: const fn = useCallback(() => {...}, [deps])
COLOCATION 2.5-bob: state'ni ishlatadigan komponentga TUSHIR (yuqori emas)
CHILDREN 2.8-bob: <Parent><Heavy/></Parent> // Heavy — Parent state'idan ta'sirlanmaydi
CONTEXT 2.9-bob: value=useMemo(...) + context'ni BO'L (auth/theme/cart alohida)
KEY RESET 2.10-bob: <Profile key={userId}/> // userId o'zgarsa state reset
VIRTUAL 2.11-bob: useVirtualizer (@tanstack/react-virtual) // 1000+ ro'yxat
DEBOUNCE 2.12-bob: useDebounce(query, 400) // tugagach 1 marta
TRANSITION 2.13-bob: const [isPending, startTransition] = useTransition()
DEFER 2.13-bob: const deferred = useDeferredValue(query)
BUNDLE 2.14-bob: import { x } from "lib-es" // tree-shaking (named import)
IMAGE 2.14-bob: <img loading="lazy" srcSet=... width=... height=... /> // WebP/AVIF
WORKER 2.14-bob: new Worker(new URL("./w.js", import.meta.url)) // og'ir hisob
VITALS 2.14-bob: import { onLCP, onINP, onCLS } from "web-vitals"
SUSPENSE 2.15-bob: <Suspense fallback={<Spinner/>}><LazyChart/></Suspense>4. Batafsil kod namunalari
Misol 1 — Keraksiz re-render (Profiler bilan ko'rinadi — 2.1, 2.3)
function App() {
const [count, setCount] = useState(0);
return (
<div>
<button onClick={() => setCount(c => c + 1)}>Count: {count}</button>
<ExpensiveList items={data} /> {/* ❗ count o'zgarsa BU HAM render (bekorga) */}
</div>
);
}
function ExpensiveList({ items }) {
console.log("ExpensiveList render"); // Profiler / konsol: count o'zgarganda ham chiqadi
return <ul>{items.map(i => <li key={i.id}>{i.name}</li>)}</ul>;
}
// ❗ Profiler "Highlight updates" — count bosganda ExpensiveList ranglanadi (keraksiz — Misol 2 tuzatadi)Misol 2 — React.memo bilan tuzatish (2.6)
const ExpensiveList = React.memo(function ExpensiveList({ items }) {
console.log("ExpensiveList render");
return <ul>{items.map(i => <li key={i.id}>{i.name}</li>)}</ul>;
});
function App() {
const [count, setCount] = useState(0);
return (
<div>
<button onClick={() => setCount(c => c + 1)}>Count: {count}</button>
<ExpensiveList items={data} /> {/* data o'zgarmasa — render BO'LMAYDI (memo) */}
</div>
);
}
// ❗ Endi count bosganda ExpensiveList render BO'LMAYDI (items bir xil — 2.6)
// LEKIN: items inline yaratilca (items={[...]}) — memo buziladi (Misol 4)Misol 3 — React.memo custom comparison (2.6)
const UserRow = React.memo(
function UserRow({ user, isSelected }) {
return <div className={isSelected ? "selected" : ""}>{user.name}</div>;
},
(prev, next) =>
prev.user.id === next.user.id && prev.isSelected === next.isSelected // faqat shu ikkisi
);
// ❗ Custom: user obyekti har render yangi bo'lsa ham, id+isSelected bir xil bo'lsa render YO'Q
// (true qaytsa — "bir xil" — render qilmaydi). Ehtiyot: noto'g'ri taqqoslash — eski UIMisol 4 — useCallback + memo to'liq (inline muammosi — 2.7, 2.10)
const TodoItem = React.memo(function TodoItem({ todo, onToggle }) {
console.log("TodoItem render:", todo.id);
return <li onClick={() => onToggle(todo.id)}>{todo.text}</li>;
});
function TodoList({ todos }) {
const [filter, setFilter] = useState("");
// ❌ const onToggle = (id) => {...} // har render yangi → memo foydasiz
// ✅ useCallback — barqaror havola → TodoItem filter o'zgarganda render BO'LMAYDI
const onToggle = useCallback((id) => {
console.log("toggle", id);
}, []);
return (
<>
<input value={filter} onChange={e => setFilter(e.target.value)} />
{todos.map(t => <TodoItem key={t.id} todo={t} onToggle={onToggle} />)}
</>
);
}
// ❗ filter yozsangiz — TodoItem'lar render BO'LMAYDI (onToggle barqaror — memo ishlaydi — 2.7)Misol 5 — useMemo qimmat hisob (2.7, 11.6)
function Analytics({ transactions }) { // katta massiv (10000+)
// Qimmat hisob — har render emas, faqat transactions o'zgarganda
const stats = useMemo(() => {
console.log("Hisoblanmoqda...");
return {
total: transactions.reduce((s, t) => s + t.amount, 0),
byCategory: transactions.reduce((acc, t) => {
acc[t.category] = (acc[t.category] || 0) + t.amount;
return acc;
}, {}),
};
}, [transactions]);
return <div>Jami: {stats.total}</div>;
}
// ❗ Boshqa state o'zgarganda (masalan UI toggle) — stats QAYTA hisoblanmaydi (kesh — 2.7)Misol 6 — State colocation (state'ni pastga tushir — 2.5)
// ❌ State yuqorida — har harf butun App'ni render qiladi:
function AppBad() {
const [search, setSearch] = useState("");
return (
<>
<input value={search} onChange={e => setSearch(e.target.value)} />
<ExpensiveTree /> {/* search o'zgarsa BU render (bekorga) */}
</>
);
}
// ✅ State pastga tushdi — search faqat SearchBox'da:
function AppGood() {
return (
<>
<SearchBox /> {/* search shu ichida */}
<ExpensiveTree /> {/* App render bo'lmaydi → bu ham render BO'LMAYDI */}
</>
);
}
function SearchBox() {
const [search, setSearch] = useState(""); // colocation — faqat shu render
return <input value={search} onChange={e => setSearch(e.target.value)} />;
}
// ❗ Eng oddiy optimizatsiya — memo'dan OLDIN buni o'yla (2.5)Misol 7 — children trick (re-render'ni to'xtatish — 2.8)
// ❌ ExpensiveTree har count o'zgarganda render:
function Bad() {
const [count, setCount] = useState(0);
return (
<div onClick={() => setCount(c => c + 1)}>
<p>{count}</p>
<ExpensiveTree /> {/* count o'zgarsa render (bekorga) */}
</div>
);
}
// ✅ children sifatida uzat — Counter state'idan ta'sirlanmaydi:
function Good() {
return (
<Counter>
<ExpensiveTree /> {/* App'da yaratildi — Counter render bo'lsa ham qayta yaralmaydi */}
</Counter>
);
}
function Counter({ children }) {
const [count, setCount] = useState(0);
return <div onClick={() => setCount(c => c + 1)}><p>{count}</p>{children}</div>;
}
// ❗ children yuqorida yaralib, barqaror havola → memo'siz re-render to'xtaydi (2.8)Misol 8 — Context bo'lish va value memo (2.9)
// ❌ Bitta context — cart o'zgarsa auth/theme consumer ham render:
// <AppContext.Provider value={{ user, theme, cart, setCart }}>
// ✅ Bo'l + value memo:
function AuthProvider({ children }) {
const [user, setUser] = useState(null);
const value = useMemo(() => ({ user, setUser }), [user]); // barqaror (11.6: 2.9)
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}
function CartProvider({ children }) {
const [cart, setCart] = useState([]);
const value = useMemo(() => ({ cart, setCart }), [cart]);
return <CartContext.Provider value={value}>{children}</CartContext.Provider>;
}
// Ishlatish:
// <AuthProvider><CartProvider><App/></CartProvider></AuthProvider>
// ❗ cart o'zgarsa — faqat useCart() consumer render (useAuth() consumer tegmaydi — 2.9)Misol 9 — key bilan state reset (2.10)
function UserProfile({ userId }) {
// userId o'zgarsa — eski state (forma, tab) tozalansin
return <ProfileForm key={userId} userId={userId} />;
// ❗ key={userId} — userId o'zgarganda React ProfileForm'ni BUTUNLAY yangidan yaratadi
// (ichki state, forma — tozalanadi). useEffect bilan qo'lda tozalashdan tozaroq (2.10)
}
function ProfileForm({ userId }) {
const [draft, setDraft] = useState(""); // userId o'zgarganda key tufayli "" ga reset
// ...
}Misol 10 — List virtualization (react-window — 2.11)
import { FixedSizeList } from "react-window";
function BigList({ items }) { // items — 10000+ element
return (
<FixedSizeList
height={600} // ko'rinadigan balandlik
itemCount={items.length} // jami (10000)
itemSize={50} // har element balandligi
width="100%"
>
{({ index, style }) => ( // faqat KO'RINADIGAN elementlar render bo'ladi
<div style={style}>{items[index].name}</div> // style — joylashuv (majburiy)
)}
</FixedSizeList>
);
}
// ❗ 10000 element bor, lekin DOM'da faqat ~12 (ko'rinadigan) — skroll'da almashadi (2.11)
// @tanstack/react-virtual — moslashuvchanroq alternativaMisol 11 — Debounce qimmat qidiruv (2.12, 11.7)
function Search({ allItems }) {
const [query, setQuery] = useState("");
const debouncedQuery = useDebounce(query, 300); // 11.7 — tugagach 300ms
// Qimmat filtr — faqat debouncedQuery o'zgarganda (har harfda emas)
const results = useMemo(
() => allItems.filter(i => i.name.toLowerCase().includes(debouncedQuery.toLowerCase())),
[allItems, debouncedQuery]
);
return (
<>
<input value={query} onChange={e => setQuery(e.target.value)} /> {/* input darrov */}
<ul>{results.map(r => <li key={r.id}>{r.name}</li>)}</ul> {/* filtr kechikadi */}
</>
);
}
// ❗ Input darrov yoziladi (responsive); qimmat filtr har harfda emas, to'xtagach (2.12)Misol 12 — useTransition (bloklamaydigan yangilanish — 2.13)
function SearchBig({ allItems }) {
const [query, setQuery] = useState("");
const [results, setResults] = useState(allItems);
const [isPending, startTransition] = useTransition();
function handleChange(e) {
setQuery(e.target.value); // SHOSHILINCH — input darrov
startTransition(() => { // SHOSHILMAS — og'ir filtr (input'ni bloklamaydi)
setResults(allItems.filter(i => i.name.includes(e.target.value)));
});
}
return (
<>
<input value={query} onChange={handleChange} />
{isPending && <span>Yangilanmoqda...</span>} {/* o'tish davom etmoqda */}
<ul style={{ opacity: isPending ? 0.5 : 1 }}>
{results.map(r => <li key={r.id}>{r.name}</li>)}
</ul>
</>
);
}
// ❗ Katta ro'yxat filtri input'ni QOTIRMAYDI (filtr fonda — useTransition — 2.13)Misol 13 — useDeferredValue (og'ir ro'yxat kechiktirish — 2.13)
function ProductSearch({ products }) {
const [query, setQuery] = useState("");
const deferredQuery = useDeferredValue(query); // query darrov; deferred kechikadi
// Og'ir ro'yxat — kechiktirilgan qiymatdan (input'ni qotirmaydi)
const filtered = useMemo(
() => products.filter(p => p.name.includes(deferredQuery)),
[products, deferredQuery]
);
const isStale = query !== deferredQuery; // kechikyaptimi?
return (
<>
<input value={query} onChange={e => setQuery(e.target.value)} /> {/* darrov */}
<ul style={{ opacity: isStale ? 0.5 : 1 }}> {/* eski'ni xira */}
{filtered.map(p => <li key={p.id}>{p.name}</li>)}
</ul>
</>
);
}
// ❗ Input darrov; og'ir ro'yxat biroz orqada (lekin UI qotmaydi — useDeferredValue — 2.13)Misol 14 — Optimizatsiya jarayoni (o'lcha → tuzat → o'lcha — 2.3, 2.16)
// 1-QADAM: Profiler bilan o'lcha (qaysi komponent sekin/ko'p render?)
// 2-QADAM: ANIQ sabab (Misol 1 — ExpensiveList ota bilan render bo'lyapti)
// 3-QADAM: MOS yechim (React.memo + barqaror props):
const Row = React.memo(function Row({ item, onSelect }) {
return <div onClick={() => onSelect(item.id)}>{item.name}</div>;
});
function Table({ data }) {
const [selected, setSelected] = useState(null);
const onSelect = useCallback((id) => setSelected(id), []); // barqaror (2.7)
return data.map(item => <Row key={item.id} item={item} onSelect={onSelect} />);
}
// 4-QADAM: QAYTA o'lcha (Profiler — endi keraksiz render yo'qmi?)
// ❗ Jarayon: o'lcha → aniqla → mos yechim → qayta o'lcha (dalilga asoslan — 2.16)Misol 15 — Web Worker (o'ta og'ir hisob — main thread'ni qotirmaslik — 2.14)
// worker.js — alohida oqimda ishlaydigan og'ir hisob
self.onmessage = (e) => {
const data = e.data;
// o'ta og'ir ish (millionlab element) — bu main thread'da bo'lsa UI qotardi
const result = data.reduce((sum, x) => sum + heavyCompute(x), 0);
self.postMessage(result); // natijani asosiy oqimga qaytar
};
// Komponent — worker'ni ishlatish (UI qotmaydi)
function HeavyStats({ data }) {
const [result, setResult] = useState(null);
useEffect(() => {
const worker = new Worker(new URL("./worker.js", import.meta.url));
worker.postMessage(data); // og'ir ishni worker'ga uzat
worker.onmessage = (e) => setResult(e.data); // natija kelganda UI yangilanadi
return () => worker.terminate(); // tozalash (memory leak yo'q)
}, [data]);
return <div>{result === null ? "Hisoblanmoqda..." : `Natija: ${result}`}</div>;
}
// ❗ useMemo render fazasini keshlaydi, LEKIN o'ta og'ir hisob main thread'ni bloklaydi
// → Web Worker alohida oqimda ishlaydi → UI silliq qoladi (interaktiv — 2.14)5. To'g'ri va noto'g'ri holatlar
1) Optimizatsiya boshlanishi
❌ Hamma joyga memo/useMemo (taxminga — premature — 2.16)
✅ Avval o'lcha (Profiler) → aniq muammoni topib tuzat (2.3)2) Re-render tushunchasi
❌ "har re-render — falokat, hammasini to'xtat" (re-render arzon — 2.2)
✅ faqat KERAKSIZ QIMMAT render'ni to'xtat (uzun ro'yxat, og'ir hisob)3) React.memo bilan props
❌ <Memo style={{...}} onClick={() => {}} /> (inline — memo buziladi — 2.10)
✅ useMemo/useCallback bilan barqaror props (2.7)4) State joyi
❌ state juda yuqorida (kichik o'zgarish katta shoxni render — 2.5)
✅ colocation — state'ni ishlatadigan joyga tushir (memo'dan oldin)5) Uzun ro'yxat
❌ 10000 element oddiy map (sekin, ko'p DOM — 2.11)
✅ virtualization (faqat ko'rinadigani — react-window/tanstack)6) Context katta/tez o'zgaradigan
❌ bitta katta context, har render yangi value (hamma consumer render — 2.9)
✅ context'ni bo'l + value memo; juda katta → Redux/Zustand (selektor — 12)6. Keng tarqalgan xatolar va yechimlari
Xato 1 — React.memo qo'shdim, lekin bola baribir render bo'ladi
Sababi: obyekt/funksiya props inline (har render yangi havola — 2.6, 2.10). Yechimi: useMemo/useCallback bilan barqaror; inline'ni tashqariga chiqar (Misol 4).
Xato 2 — useMemo/useCallback qo'shdim, tezroq bo'lmadi (yoki sekinroq)
Sababi: arzon hisob/memo'siz bola — ortiqcha (2.7, 11.6: 2.13). Yechimi: Profiler bilan o'lcha; faqat haqiqiy qimmat joyni optimallashtir.
Xato 3 — Sahifa uzun ro'yxat bilan qotadi/lag
Sababi: 1000+ element to'liq render/DOM'da 2.11-bob. Yechimi: virtualization (react-window / @tanstack/react-virtual).
Xato 4 — Jonli qidiruv har harfda qotadi
Sababi: har keystroke qimmat filtr/so'rov 2.12-bob. Yechimi: debounce 2.12-bob yoki useDeferredValue 2.13-bob.
Xato 5 — Context o'zgarganda butun ilova render bo'ladi
Sababi: bitta katta context, har render yangi value 2.9-bob. Yechimi: value memo + context bo'lish (Misol 8); katta state → Redux/Zustand.
Xato 6 — Custom React.memo comparison eski UI ko'rsatadi
Sababi: comparison funksiyasi muhim propni tekshirmadi (noto'g'ri "bir xil" — 2.6). Yechimi: comparison'ga barcha muhim propni qo'sh, yoki uni umuman olib tashla (default shallow).
Xato 7 — Optimizatsiyadan keyin xato natija (eski qiymat)
Sababi: useMemo/useCallback deps to'liq emas (stale — 11.5: 2.9). Yechimi: exhaustive-depsga rioya (barcha ishlatilgan qiymat deps'da).
7. Integratsiya — bu mavzu stack'ning qayerida uchraydi
- memo/useMemo/useCallback 11.6-bob: bu bob ularni performance rakursidan birlashtiradi.
- Render mexanizmi (11.2: 2.2): render vs commit — performance asosi 2.2-bob.
- State 11.4-bob: colocation — state joyi performance'ga ta'sir qiladi 2.5-bob.
- Context/hooks 11.5-bob: context optimizatsiyasi, useTransition/useDeferredValue (2.9, 2.13).
- Code splitting 11.8-bob: bundle performance, tree-shaking, dynamic import, Suspense/lazy (yuklanish o'lchami — 2.14, 2.15).
- Custom hooks 11.7-bob: useDebounce — qimmat hodisalar 2.12-bob.
- State management (12): Redux/Zustand selektorlar — Context'dan tez (katta state — 2.9).
- Core Web Vitals 13.8-bob: LCP/INP/CLS,
web-vitalsbilan real o'lchov — SEO/UX 2.14-bob. - SSR/streaming (15-QISM): Next.js/Remix — server render, streaming, RSC (yuklanish tajribasi — 2.15).
8. Eng yaxshi amaliyotlar (best practices)
- O'lchang, taxmin qilmang (Profiler → aniq muammo → tuzating — 2.3, 2.16).
- To'g'ri > tez (avval ishlaydigan kod; optimizatsiya muammo bo'lsa — premature emas).
- Colocation avval (state'ni pastga tushiring — memo'dan oldin — 2.5).
- memo + useMemo + useCallback birga (referential barqarorlik — 2.6, 2.7).
- Inline obyekt/funksiyani memo'li bolaga bermaslik (memo'ni buzadi — 2.10).
- children trick (memo'siz re-render to'xtatish — 2.8).
- Context'ni bo'l + value memo (yoki katta state → Redux/Zustand — 2.9).
- Uzun ro'yxat → virtualization (1000+ element — majburiy — 2.11).
- Qimmat hodisa → debounce/throttle/defer (qidiruv, skroll — 2.12, 2.13).
- O'ta og'ir hisob → Web Worker (main thread'ni qotirmaslik — useMemo yetmaganda — 2.14).
- Yuklanishni ham optimallashtirish (bundle tree-shaking, rasm lazy/WebP, Web Vitals o'lchash — 2.14).
- React Compiler'ni ko'rib chiqish (avto-memo — qo'lda ishni kamaytiradi — 2.16).
9. Amaliy loyiha: "Katta Ma'lumotli Dashboard (Performance)"
O'lchovga asoslangan optimizatsiyani real, og'ir ilovada mustahkamlash.
Maqsad
Katta ma'lumotli dashboard (10 000+ qatorli jadval, jonli qidiruv, grafiklar) yarating va uni Profiler bilan o'lchab, maqsadli optimallashtiring.
Talablar (requirements)
- Katta ro'yxat: 10 000+ elementli ro'yxat/jadval — virtualization bilan (Misol 10, 2.11).
- Jonli qidiruv: debounce yoki useDeferredValue bilan (input qotmasin — Misol 11, 13).
- React.memo: ro'yxat satrlari memoizatsiyalansin + barqaror props (Misol 4, 2.6).
- useMemo: qimmat hisob (statistika, filtr) keshlansin (Misol 5, 2.7).
- Colocation: har state'ni mumkin qadar past joyda tuting (Misol 6, 2.5).
- Context: agar global state bo'lsa — bo'lingan + value memo (Misol 8, 2.9).
- Profiler: har optimizatsiyadan oldin/keyin o'lchang (render soni/vaqt — 2.3).
- useTransition: og'ir filtr/tab almashishda UI responsive (Misol 12, 2.13).
- children trick yoki key reset: kamida bittasini qo'llang (Misol 7, 9).
- Hujjat: har optimizatsiyani NEGA qo'yganingizni (Profiler dalili bilan) yozing 2.16-bob.
Maslahatlar (hint)
- AVVAL optimizatsiyasiz yozing va Profiler bilan sekinlikni ko'ring (qaysi komponent — 2.3).
- 10000 ro'yxat — virtualization majburiy (oddiy map qotadi — 2.11).
- React.memo faqat barqaror props bilan ishlaydi (inline bermang — Misol 4).
- Qimmat hisobni useMemo; lekin arzonni emas (Profilerda tekshiring — 2.7, 2.13).
- Jonli qidiruvda input darrov, ro'yxat kechiksa mayli (useDeferredValue — Misol 13).
- Har optimizatsiyadan keyin QAYTA o'lchang — foyda bo'ldimi? 2.16-bob.
"Tayyor" mezonlari (acceptance criteria)
- 10000+ ro'yxat virtualization bilan (DOM'da ~ko'rinadigani).
- Jonli qidiruv input'ni qotirmaydi (debounce/defer).
- Ro'yxat satrlari memo + barqaror props (keraksiz render yo'q).
- Qimmat hisob useMemo bilan keshlangan.
- State colocation qo'llangan.
- Profiler bilan oldin/keyin o'lchangan (dalil bor).
- useTransition yoki useDeferredValue ishlatilgan.
- Har optimizatsiya oqlangan (Profiler dalili — taxmin emas).
Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.
10. Xulosa va keyingi bobga ko'prik
Bu bobda React performance optimizatsiyasini chuqur o'rgandik:
- Re-render (qachon/nega — 2.1); render ≠ DOM update 2.2-bob; o'lchash (Profiler — 2.3); sabablar va yechimlar 2.4-bob.
- Colocation 2.5-bob; React.memo 2.6-bob; useMemo/useCallback (perf — 2.7); children trick 2.8-bob; Context optimizatsiyasi 2.9-bob; inline/key 2.10-bob.
- Virtualization (uzun ro'yxat — 2.11); debounce/throttle 2.12-bob; concurrent (useTransition/useDeferredValue — 2.13); bundle/rasm/web worker/Web Vitals 2.14-bob; Suspense va SSR/streaming 2.15-bob; React Compiler va tafakkur 2.16-bob.
Endi siz sekin React ilovasini Profiler bilan tashxis qo'yib, aniq muammoni topib, mos yechim bilan tezlashtira olasiz — va eng muhimi, "o'lchang, taxmin qilmang" tafakkuriga egasiz. Bu — senior React dasturchisining eng aniq belgilaridan biri.
Keyingi bob — 11.12-bob: Error boundaries, portals, refs (ilg'or). React'ning ilg'or imkoniyatlarini ko'ramiz: Error boundaries (xatolarni ushlab, butun ilova qulashining oldini olish — 11.8'da lazy bilan ko'rdik, endi chuqur), Portals (komponentni DOM daraxtining boshqa joyiga "teleport" qilish — modal, tooltip, dropdown uchun), va refs (useRef, forwardRef, useImperativeHandle — DOM va komponentga imperativ kirish). Bular — murakkab, qayta ishlatiladigan komponentlar (modal tizimi, UI kutubxonalar) qurish uchun zarur.
Foydalanilgan rasmiy/ishonchli manbalar
- React rasmiy hujjati (react.dev) — "Render and Commit", "Render and Commit — bailout",
memo,useMemo,useCallback, "Passing Data Deeply with Context" - react.dev —
useTransition,useDeferredValue, "Keeping Components Pure", "Suspense",lazy; React DevTools Profiler hujjati ("Profiler API", "highlight updates") - React Compiler rasmiy hujjati (react.dev/learn/react-compiler)
- Virtualization kutubxonalari:
@tanstack/react-virtual,react-window,react-virtuosorasmiy hujjatlari - web.dev — Core Web Vitals (LCP, INP, CLS), "Optimize long tasks", "Web Workers";
web-vitalsnpm kutubxonasi - MDN —
Worker,<img loading>,srcset/sizes, WebP/AVIF format hujjatlari - Bundle tahlili:
rollup-plugin-visualizer,source-map-explorer; Vite/webpack "code splitting" hujjatlari - Kent C. Dodds — "Fix the slow render before you fix the re-render", "One React mistake that's slowing you down" (state colocation)
O'qiganingizni mustahkamlang
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!