IlmHamroh
Dasturlash kitobi (eski nashr)/11-QISM — React11/17-dars42 daqiqa
Mundarija (46)

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)

text
  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)

text
  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'da

Re-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)

text
  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 memo qo'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

text
  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 aniqla

Re-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.memo 2.6-bob, yoki state'ni pastga tushirish 2.5-bob, yoki children trick 2.8-bob. (2) Yangi obyekt/funksiya props (har render yangi havola — 11.6: 2.9): yechim — useMemo/useCallback 2.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 — memo hamma 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

text
  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 — masalan search state App'da bo'lsa, har harf yozilganda HugeExpensiveList ham bekorga render bo'ladi (sekin). Yechim — state'ni faqat uni ishlatadigan komponentga tushirish: searchni SearchBox ichiga ko'chirsangiz, har harfda faqat SearchBox render bo'ladi, HugeExpensiveList tegmaydi (chunki App endi 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'pincha memo qo'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

text
  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.memo chuqur — komponentni o'rab, props o'zgarmasa re-render qilmaydigan HOC (11.6: 2.12 chuqurroq). React.memo(ProductCard) — ota render bo'lsa ham, agar product/onAdd props o'zgarmagan bo'lsa, ProductCard render 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'larini useMemo/useCallback bilan barqaror ushlash kerak 2.7-bob — aks holda React.memo foydasiz 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) — faqat id bo'yicha solishtirish (true qaytsa 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 + useCallback uchalasi 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

text
  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/useCallback performance 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, faqat bigList o'zgarganda — 11.6: 2.8). (2) Referential barqarorlik — React.memo'li bolaning re-render'ini to'xtatish: obyekt prop'ni useMemo, funksiya prop'ni useCallback bilan barqaror ushlaysiz, shunda React.memo haqiqatan ishlaydi (2.6, 11.6: 2.9). Qachon kerak (perf): React.memo'li bolaga obyekt/funksiya prop; useEffect/useMemo deps'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.memo bilan birga); yolg'iz useCallback (memo'siz bolaga beriladigan funksiya) — foydasiz (faqat React.memo bilan ma'noli — 2.6). Bu uchligi (memo + useMemo + useCallback) doim birga ishlatiladi.

2.8. children prop fokusi — re-render'ni to'xtatish

text
  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)

children prop trick — re-render'ni memosiz to'xtatishning nafis usuli. G'oya: children sifatida uzatilgan JSX ota komponentda (yuqorida) yaratiladi, shuning uchun state state-tutuvchi komponent re-render bo'lganda qayta yaralmaydi (havolasi bir xil qoladi). Misol: agar ExpensiveTree count state-tutuvchi div ichida bevosita bo'lsa, har count o'zgarganda ExpensiveTree ham bekorga render bo'ladi. Lekin ExpensiveTreeni <Counter>ga children sifatida uzatsangiz (<Counter><ExpensiveTree /></Counter>), ExpensiveTree Appda yaratiladi (yuqorida), va Counter o'z count'ini o'zgartirganda children (ya'ni ExpensiveTree) 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 — children yuqorida 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

text
  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 ehtiyot

Context 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 yangi value obyekti (referential — 11.6: 2.9). Yechim 1 — valueni useMemo bilan 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 — shunda cart o'zgarganda faqat CartContext consumer'lari render bo'ladi (auth/theme tegmaydi). Ikki strategik nuqta: (1) value memo + 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

text
  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) — bu React.memo'li bolaga berilsa, memo buziladi (bola har doim "yangi prop" ko'radi → render). Yechim — ularni useMemo/useCallback bilan tashqariga chiqarish (barqaror havola). Eslatma: memo'siz oddiy bolada inline yaxshi (oddiy va tez), faqat memo'li bola bilan muammo. key bilan state reset — boshqa foydali naqsh: komponentga key berib, u o'zgarganda React komponentni butunlay yangi (o'chirib-qayta yaratadi) qiladi, shuning uchun ichki state tozalanadi (<Profile key={userId} /> — userId o'zgarganda Profile yangidan boshlanadi). Bu — eski state'ni useEffect bilan 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) key o'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

text
  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). useVirtualizer hook'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

text
  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.7 useDebounce): 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 — useDebounce custom hook 11.7-bob, lodash debounce/throttle, yoki React 19'ning useDeferredValue 2.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

text
  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) ideal

Concurrent (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 (setQuery shoshilinch), og'ir filtr esa fonda (input'ni bloklamaydi); isPending o'tish davom etayotganini ko'rsatadi (spinner). useDeferredValue — qiymatning "kechiktirilgan" nusxasini beradi: const deferredQuery = useDeferredValue(query) — query darrov o'zgaradi (input responsive), deferredQuery biroz 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) useDeferredValue debounce'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)

text
  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 rasmga width/height berish (CLS — layout siljimasin). (B) Web worker — useMemo render 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, natijani postMessage bilan 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-vitals kutubxonasi (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)

text
  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 qaratilgan

Suspense 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 (isLoading state'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

text
  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.memo kerakligini 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 joyga memo tiqishtirish (kod murakkablashadi, foyda yo'q). Senior dasturchi — tashxis qo'yib, aniq davo beradi.


3. Sintaksis — tez ma'lumotnoma

text
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)

jsx
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)

jsx
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)

jsx
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 UI

Misol 4 — useCallback + memo to'liq (inline muammosi — 2.7, 2.10)

jsx
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)

jsx
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)

jsx
// ❌ 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)

jsx
// ❌ 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)

jsx
// ❌ 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)

jsx
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)

jsx
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 alternativa

Misol 11 — Debounce qimmat qidiruv (2.12, 11.7)

jsx
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)

jsx
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)

jsx
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)

jsx
// 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)

jsx
// 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

text
❌ Hamma joyga memo/useMemo (taxminga — premature — 2.16)
✅ Avval o'lcha (Profiler) → aniq muammoni topib tuzat (2.3)

2) Re-render tushunchasi

text
❌ "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

text
❌ <Memo style={{...}} onClick={() => {}} />  (inline — memo buziladi — 2.10)
✅ useMemo/useCallback bilan barqaror props (2.7)

4) State joyi

text
❌ state juda yuqorida (kichik o'zgarish katta shoxni render — 2.5)
✅ colocation — state'ni ishlatadigan joyga tushir (memo'dan oldin)

5) Uzun ro'yxat

text
❌ 10000 element oddiy map (sekin, ko'p DOM — 2.11)
✅ virtualization (faqat ko'rinadigani — react-window/tanstack)

6) Context katta/tez o'zgaradigan

text
❌ 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-vitals bilan 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)

  1. Katta ro'yxat: 10 000+ elementli ro'yxat/jadval — virtualization bilan (Misol 10, 2.11).
  2. Jonli qidiruv: debounce yoki useDeferredValue bilan (input qotmasin — Misol 11, 13).
  3. React.memo: ro'yxat satrlari memoizatsiyalansin + barqaror props (Misol 4, 2.6).
  4. useMemo: qimmat hisob (statistika, filtr) keshlansin (Misol 5, 2.7).
  5. Colocation: har state'ni mumkin qadar past joyda tuting (Misol 6, 2.5).
  6. Context: agar global state bo'lsa — bo'lingan + value memo (Misol 8, 2.9).
  7. Profiler: har optimizatsiyadan oldin/keyin o'lchang (render soni/vaqt — 2.3).
  8. useTransition: og'ir filtr/tab almashishda UI responsive (Misol 12, 2.13).
  9. children trick yoki key reset: kamida bittasini qo'llang (Misol 7, 9).
  10. 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-virtuoso rasmiy hujjatlari
  • web.dev — Core Web Vitals (LCP, INP, CLS), "Optimize long tasks", "Web Workers"; web-vitals npm 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)
Ulashish:Telegram'da

O'qiganingizni mustahkamlang

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
11.11-bob: Performance optimizatsiya (memo, re-render) — IlmHamroh