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