WisarWisar
Dasturlash kitobi/11-QISM — React42 daqiqa

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'lcha, taxmin qilma (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'lcha, taxmin qilma" tafakkuri — junior'ni senior'dan ajratadi (dalilga asoslan).
  • 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 barqarorlikReact.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 1valueni 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'l.

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 BERMA (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 berma (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)

   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 splittinglazy(() => 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'lcha, taxmin qilma". (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 workeruseMemo 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'lcha, taxmin qilma" 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 yozsang — 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'lcha, taxmin qilma (Profiler aniq muammo tuzat — 2.3, 2.16).
  • To'g'ri > tez (avval ishlaydigan kod; optimizatsiya muammo bo'lsa — premature emas).
  • Colocation avval (state'ni pastga tushir — memo'dan oldin — 2.5).
  • memo + useMemo + useCallback birga (referential barqarorlik — 2.6, 2.7).
  • Inline obyekt/funksiya memo'li bolaga berma (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 qotirma — useMemo yetmaganda — 2.14).
  • Yuklanishni ham optimallashtir (bundle tree-shaking, rasm lazy/WebP, Web Vitals o'lchash — 2.14).
  • React Compiler'ni ko'rib chiq (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) yarat va uni Profiler bilan o'lchab, maqsadli optimallashtir.

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 tut (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'lcha (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'lla (Misol 7, 9).
  10. Hujjat: har optimizatsiyani NEGA qo'yganingizni (Profiler dalili bilan) yozing 2.16-bob.

Maslahatlar (hint)

  • AVVAL optimizatsiyasiz yoz va Profiler bilan sekinlikni ko'r (qaysi komponent — 2.3).
  • 10000 ro'yxat — virtualization majburiy (oddiy map qotadi — 2.11).
  • React.memo faqat barqaror props bilan ishlaydi (inline berma — Misol 4).
  • Qimmat hisobni useMemo; lekin arzonni emas (Profiler tekshir — 2.7, 2.13).
  • Jonli qidiruvda input darrov, ro'yxat kechiksa mayli (useDeferredValue — Misol 13).
  • Har optimizatsiyadan keyin QAYTA o'lcha — 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'lcha, taxmin qilma" 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)

Izohlar (0)

Izoh yozish uchun kiring.

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