Mundarija (29)
- Bu darsda
- 1. Nega bu kerak?
- 2. Muammo: tez state yuqorida
- 2.1 Aksiya matni va og'ir menyu
- 3. State'ni pastga tushirish
- 3.1 State uni ishlatadiganlar yoniga
- 3.2 Bu State'ni ko'tarish ga zidmi?
- 3.3 Komponentni ajratish
- 4. Children orqali uzatish
- 4.1 State og'ir qismni o'raydi
- 4.2 Og'ir qism — children
- 4.3 Nega ishlaydi
- 5. Provider'ni pastga tushirish
- 5.1 Provider — children li o'ram
- 5.2 Provider qayerda turishi kerak
- 6. Qachon yordam bermaydi
- 7. Vazifalar qadami: tema — kompozitsiya ishda (o'lchov, commit yo'q)
- 7.1 Kanon kodi
- 7.2 O'lchov va qaror
- 7.3 Qolgan joylar
- 8. Ko'p uchraydigan xatolar
- 9. Mashqlar
- 1-mashq (oson): qaysi usul?
- 2-mashq (o'rta): buyurtma vaqti
- 3-mashq (qiyin): retsept paneli
- 4-mashq: vazifalar — kim state'ni o'qiydi?
- 10. Real ishda
- Xulosa
- Manbalar
Kompozitsiya orqali optimallashtirish: memo'siz kamroq render
Qisqacha:
memodan oldin kodning tuzilishini o'zgartiring. Ikki usul ko'p renderni bepul yo'qotadi. Birinchisi — state'ni pastga tushirish: tez o'zgaradigan state uni ishlatadigan kichik komponentga ko'chadi, qolgan sahifa chizilmaydi. Ikkinchisi — children orqali uzatish: state'li o'ram og'ir qismnichildrensifatida oladi, uni esa ota yasagan, demak o'ram chizilganda u tegilmaydi. Provider'lar ham shunday quriladi:<TemaProvider><App /></TemaProvider>da tema almashgandaAppumuman chizilmaydi —vazifalarda o'lchangan: 2 render.
Bu darsda
- State'ni pastga tushirib (colocation), keraksiz renderlarni yo'qotasiz.
childrenorqali uzatish negamemosiz ishlashini Fiber darajasida tushuntirasiz.- Tez yangilanadigan qismni alohida komponentga ajratasiz.
- Provider'ni
childrennaqshi bilan yozib, iste'molchi bo'lmaganlarni himoya qilasiz. - Kompozitsiya qachon yordam bermasligini bilasiz.
Oldin bilishingiz kerak: Qayta render sabablari va miflar, children va kompozitsiya, State'ni ko'tarish, Context I.
1. Nega bu kerak?
Qayta render sabablari darsida uchta sababni topdik: o'z state'i, ota render va context. memo faqat bittasini — "ota chizildi" ni — to'xtatadi. Buning narxi ham bor: props solishtiriladi, yangi obyekt yoki funksiya berilsa — ishlamaydi.
Lekin "ota chizildi" sababining o'zini yo'qotsa-chi? Agar og'ir komponent tez o'zgaradigan state'ning ostida bo'lmasa, uni to'xtatishga hojat qolmaydi. Bu — kompozitsiya: komponentlarni boshqacha joylashtirish. React jamoasining tavsiyasi ham shu tartibda: avval tuzilish, keyin memo (react.dev, memo sahifasi, "Minimizing props changes" va "Optimizing with memo" bo'limlari).
Hayotiy o'xshatish: «Bahor» oshxonasida kassada har daqiqada chek chiqadi. Agar kassa oshxona o'rtasida tursa, har chekda hamma oshpaz boshini ko'taradi. Kassani eshik yoniga ko'chirsangiz — oshpazlar ishlayveradi. Hech kimga "e'tibor berma" deb o'rgatish (memo) shart emas.
2. Muammo: tez state yuqorida
2.1 Aksiya matni va og'ir menyu
Jasur aka sahifa tepasidagi aksiya matnini yozadi. Pastda — og'ir menyu (Menu, haqiqiy loyihada yuzlab karta). Matn App ning state'ida. Konsolda Menu chizildi qatorlarini sanang:
import { useState } from "react";
function Menu() {
console.log("Menu chizildi");
return (
<ul>
<li>Osh — 35000</li>
<li>Manti — 30000</li>
</ul>
);
}
function App() {
const [promo, setPromo] = useState("");
console.log("App:", promo);
return (
<main>
<input
placeholder="Aksiya"
value={promo}
onChange={(e) => setPromo(e.target.value)}
/>
<p>Bugun: {promo}</p>
<Menu />
</main>
);
}Konsolda:
App:
Menu chizildi
App: Osh -10%
Menu chizildi
App: Osh -15%
Menu chizildiHar o'zgarishda Menu qayta chizildi. U promo ni umuman ishlatmaydi — sababi faqat "ota chizildi". Haqiqiy klaviaturada bu har harf degani.
3. State'ni pastga tushirish
3.1 State uni ishlatadiganlar yoniga
promo ni kim ishlatadi? Faqat input va <p>. Demak, state shu ikkisi bilan birga alohida komponentga ko'chadi. Bu state colocation (state'ni yoniga joylash) — state'ni uni ishlatadigan eng pastki umumiy komponentda saqlash:
import { useState } from "react";
function Menu() {
console.log("Menu chizildi");
return (
<ul>
<li>Osh — 35000</li>
<li>Manti — 30000</li>
</ul>
);
}
function PromoEditor() {
const [promo, setPromo] = useState("");
console.log("PromoEditor:", promo);
return (
<>
<input
placeholder="Aksiya"
value={promo}
onChange={(e) => setPromo(e.target.value)}
/>
<p>Bugun: {promo}</p>
</>
);
}
function App() {
console.log("App");
return (
<main>
<PromoEditor />
<Menu />
</main>
);
}Konsolda:
App
PromoEditor:
Menu chizildi
PromoEditor: Osh -10%
PromoEditor: Osh -15%Menu endi faqat bir marta — birinchi chizishda. App ham qayta chizilmaydi: unda state yo'q. Render PromoEditor dan pastga ketadi, Menu esa uning yonida, ostida emas (Qayta render sabablari dagi "pastga" qoidasi).
3.2 Bu State'ni ko'tarish ga zidmi?
Yo'q, bu o'sha qoidaning ikkinchi yarmi. State'ni ko'tarish darsida qoida shunday edi: state'ni uni ishlatadigan komponentlarning eng yaqin umumiy otasiga qo'ying. Ikki komponent bitta qiymatni ko'rsa — yuqoriga. Faqat bittasi ko'rsa — keraksiz yuqori turmasin, pastga.
Ko'p loyihada state vaqt o'tishi bilan "yuqoriga suzib chiqadi": bir paytlar ikki joyda kerak bo'lgan, keyin bitta joy qolgan, state esa App da qolib ketgan. Davriy savol foydali: "bu state'ni kim o'qiydi?"
Tekshirib ko'ring: Ertaga Jasur aka aksiya matnini menyu sarlavhasida ham ko'rsatishni so'radi.
promoqayerda yashashi kerak vaMenuyana har harfda chiziladimi?
Javob
Endi promo ni ikki komponent o'qiydi — PromoEditor va Menu. Demak, yana umumiy otaga (App) ko'tariladi va Menu har harfda chiziladi — chunki u endi promo ga haqiqatan bog'liq. Bunda keraksiz render yo'q, kerakli render bor. Agar Menu ning faqat sarlavhasi bog'liq bo'lsa, sarlavhani alohida komponentga ajrating va promo ni faqat unga bering — og'ir ro'yxat qismi baribir chizilmaydi.
3.3 Komponentni ajratish
Xuddi shu usulning yana bir ko'rinishi — komponentni ajratish: tez yangilanadigan kichik qismni o'z komponentiga chiqarish. Masalan, sahifa burchagidagi soat har soniya setNow qiladi. Soat App ichida yozilgan bo'lsa — butun sahifa har soniya chiziladi. <Clock /> ga ajratilsa — faqat u.
Bu vazifalar da allaqachon bor: e'lon taymeri useElon hook'iga, statistika paneli — StatistikaPaneli ga ajratilgan (Custom hooklar I). Lekin diqqat: hook'ga ajratish renderni kamaytirmaydi — hook'ning state'i baribir uni chaqirgan komponentniki. Renderni faqat komponentga ajratish kamaytiradi.
4. Children orqali uzatish
4.1 State og'ir qismni o'raydi
Ba'zan state'ni pastga tushirib bo'lmaydi: u og'ir qismning atrofida kerak. Masalan, menyu fonining rangi — state, menyu esa shu fon ichida:
import { useState } from "react";
function Menu() {
console.log("Menu chizildi");
return (
<ul>
<li>Osh — 35000</li>
<li>Manti — 30000</li>
</ul>
);
}
function App() {
const [color, setColor] = useState("black");
console.log("App:", color);
return (
<div style={{ color }}>
<button onClick={() => setColor("red")}>Qizil</button>
<button onClick={() => setColor("green")}>Yashil</button>
<Menu />
</div>
);
}Konsolda:
App: black
Menu chizildi
App: red
Menu chizildi
App: green
Menu chizildi<div style={{ color }}> va <Menu /> bitta komponentda. Menu ni div dan tashqariga chiqarib bo'lmaydi — u rangni meros oladi.
4.2 Og'ir qism — children
Yechim: rangli o'ramni alohida komponent qilamiz, Menu ni esa unga children sifatida beramiz (children va kompozitsiya):
import { useState } from "react";
function Menu() {
console.log("Menu chizildi");
return (
<ul>
<li>Osh — 35000</li>
<li>Manti — 30000</li>
</ul>
);
}
function ColorBox({ children }) {
const [color, setColor] = useState("black");
console.log("ColorBox:", color);
return (
<div style={{ color }}>
<button onClick={() => setColor("red")}>Qizil</button>
<button onClick={() => setColor("green")}>Yashil</button>
{children}
</div>
);
}
function App() {
console.log("App");
return (
<ColorBox>
<Menu />
</ColorBox>
);
}Konsolda:
App
ColorBox: black
Menu chizildi
ColorBox: red
ColorBox: greenEkranda:
QizilYashil
Osh — 35000
Manti — 30000| Qadam | Kim chizildi | Nega |
|---|---|---|
| birinchi chizish | App, ColorBox, Menu |
hammasi yangi |
| «Qizil» | faqat ColorBox |
o'z state'i; children — o'sha element |
| «Yashil» | faqat ColorBox |
xuddi shunday |
Menu faqat bir marta chizildi — lekin u hali ham rangli div ichida (ekranda rang o'zgaradi). memo yo'q. Qanday?
4.3 Nega ishlaydi
Reconciliation darsini eslang: <Menu /> — oddiy element obyekti. Uni kim yasadi? App — o'z renderida. ColorBox esa uni tayyor holda children props'ida oladi va JSX'ga qo'yadi.
Rang o'zgarganda faqat ColorBox qayta chiziladi (o'z state'i). App chizilmaydi — demak, <Menu /> elementi yangidan yasalmaydi. ColorBox ning yangi renderida children — o'sha obyekt, oldingi renderdagisi. React Fiber'ni ishlayotganda buni ko'radi: element o'sha, props obyekti o'sha (eskiProps === yangiProps) — demak, bu qismni qayta chizishga sabab yo'q. Bu tekshiruv memo siz ham har komponent uchun bor: memo faqat props mazmunini solishtiradi, bu esa props obyektining o'zini.
flowchart TD
A["App: Menu elementini yasaydi"] --> B["ColorBox: children"]
B --> C{"Rang o'zgardi"}
C --> D["ColorBox qayta chiziladi"]
D --> E{"children o'sha obyektmi?"}
E -->|"ha: App chizilmadi"| F["Menu tegilmaydi"]
E -->|"yo'q: App ham chizildi"| G["Menu chiziladi"]Diagrammaning pastki o'ng shoxiga qarang: agar App ham chizilsa (masalan, App ning o'z state'i o'zgarsa), yangi <Menu /> yasaladi va Menu chiziladi. Kompozitsiya ColorBox ichidagi o'zgarishlardan himoya qiladi, yuqoridagilardan emas.
Maslahat:
children— yagona slot emas. Har qanday JSX props ham shunday ishlaydi:<Layout sidebar={<Menu />} header={<Logo />}>. Elementlarni yuqorida yasang, state'li komponentga tayyor holda bering.
Tekshirib ko'ring:
ColorBoxichida{children}o'rniga<Menu />deb to'g'ridan-to'g'ri yozilsa (vaAppda<ColorBox />bo'sh bo'lsa), rang o'zgargandaMenuchiziladimi?
Javob
Chiziladi. Endi <Menu /> elementini ColorBox ning o'zi yasaydi — har renderda yangi element, yangi props obyekti. Bu «Children orqali uzatish» dan oldingi holatga qaytish: og'ir qism yana state egasining renderida tug'iladi. Qoida: og'ir elementni state'dan yuqorida yasang.
5. Provider'ni pastga tushirish
5.1 Provider — children li o'ram
Context'da ham aynan shu naqsh. Ko'p loyihada provider'lar App ning eng tepasida, state esa App ning o'zida:
function App() {
const [theme, setTheme] = useState("yorug'"); // ❌ butun App
return (
<ThemeContext value={{ theme, setTheme }}>
<Header />
<Menu />
<Footer />
</ThemeContext>
);
}Tema almashsa — App chiziladi, demak Header, Menu, Footer va ularning hamma bolalari. Ulardan faqat bittasi temani o'qisa ham.
Yechim — «Children orqali uzatish» ning o'zi: state va context'ni alohida provider komponentiga, ilovani esa children ga:
import { createContext, use, useState } from "react";
const ThemeContext = createContext(null);
function ThemeProvider({ children }) {
const [theme, setTheme] = useState("yorug'");
console.log("ThemeProvider:", theme);
return (
<ThemeContext value={{ theme, setTheme }}>
{children}
</ThemeContext>
);
}
function ThemeToggle() {
const { theme, setTheme } = use(ThemeContext);
console.log("ThemeToggle:", theme);
return (
<button onClick={() => setTheme("qorong'i")}>Qorong'i</button>
);
}
function Menu() {
console.log("Menu");
return <p>Osh, Manti</p>;
}
function App() {
console.log("App");
return (
<main>
<ThemeToggle />
<Menu />
</main>
);
}
export default function Root() {
return (
<ThemeProvider>
<App />
</ThemeProvider>
);
}Konsolda:
ThemeProvider: yorug'
App
ThemeToggle: yorug'
Menu
ThemeProvider: qorong'i
ThemeToggle: qorong'iBosishdan keyin — atigi ikki qator. ThemeProvider (o'z state'i) va ThemeToggle (context o'qiydi). App va Menu — yo'q: <App /> elementini Root yasagan, ThemeProvider uni children da tayyor holda oldi. Context qiymati har renderda yangi obyekt ({ theme, setTheme }) — lekin bu faqat iste'molchilarga ta'sir qiladi, bu yerda esa iste'molchi bitta.
5.2 Provider qayerda turishi kerak
"Pastga tushirish" provider uchun ikki ma'noda:
- Kod sifatida — state'ni
Appdan provider komponentiga ko'chirish (yuqoridagi misol). - Daraxtda — provider'ni faqat kerakli qismni o'raydigan qilib qo'yish. Savatcha context'i faqat buyurtma sahifasida kerak bo'lsa, uni butun ilova atrofiga emas, shu sahifa atrofiga qo'ying. Kamroq iste'molchi — kamroq render, kod ham o'qilishi oson.
Lekin ehtiyot bo'ling: provider ostidan chiqib ketgan iste'molchi createContext dagi standart qiymatni oladi (bizda null) — Context I dagi "Provider yo'q" xatosi. Shuning uchun vazifalar dagi useTema() null da aniq xato tashlaydi.
6. Qachon yordam bermaydi
Kompozitsiya — birinchi qadam, lekin har joyda emas:
| Holat | Nega kompozitsiya yetmaydi | Keyingi qadam |
|---|---|---|
| state'ni ko'p joy yozadi va o'qiydi | pastga tushirib bo'lmaydi | o'lchang; kerak bo'lsa memo |
| og'ir komponent state'ga haqiqatan bog'liq | render kerakli, keraksiz emas | useDeferredValue, virtualizatsiya |
| ro'yxatdagi 1 000 qatordan bittasi o'zgardi | qatorlar bitta massivdan | memo + barqaror obyektlar |
| context'ni ko'p komponent o'qiydi, qiymat obyekt | har iste'molchi chiziladi | qiymatni useMemo, context'ni bo'lish |
Uchinchi qator — vazifalar dagi 18 056 renderning holati. Ro'yxat vazifalar massividan chiziladi, bitta vazifa o'zgarsa massiv yangi. Bunda tuzilishni o'zgartirish yordam bermaydi — keyingi darsning memo si kerak.
7. Vazifalar qadami: tema — kompozitsiya ishda (o'lchov, commit yo'q)
7.1 Kanon kodi
Kanonda #19 alohida qadam emas — holat 20 ning bir qismi (QADAMLAR.md: "#19 R-64 kompozitsiya — yuqoridagi tema misoli"). Kompozitsiya 17-qismdan beri bor, biz faqat uni o'lchadik. main.tsx (holat 12):
flushSync(() => {
createRoot(ildiz, ildizSozlamasi).render(
<StrictMode>
<TemaProvider>
<App
boshlangichRoyxat={yukla() ?? boshlangichVazifalar}
qoralama={qoralamaniOl()}
/>
</TemaProvider>
</StrictMode>,
);
});<App … /> elementini modul kodi yasaydi va TemaProvider ga children qilib beradi — «Provider — children li o'ram» dagi Root ning aynan o'zi. TemaProvider (kontekst/TemaKonteksti.tsx, Context II da yozilgan):
export function TemaProvider({ children }: { children: ReactNode }) {
// Funksiya — localStorage faqat birinchi renderda o'qiladi
const [tanlov, setTanlov] = useState(saqlanganTanlov);
…
// React 19: <Context value> — .Provider yozish shart emas.
// Qiymat har renderda yangi obyekt — iste'molchilar ham qayta
// chiziladi; bizda bitta kichik iste'molchi, o'lchash va memo —
// 18-qism
return (
<TemaKonteksti value={{ tanlov, tanla }}>{children}</TemaKonteksti>
);
}Izoh qatorlari telefonga sig'ishi uchun qayta bo'lindi, return qatori — kanondagidek. 17-qismda yozilgan izoh va'da bergan edi: "o'lchash va memo — 18-qism". Endi o'lchaymiz.
7.2 O'lchov va qaror
olchov/renderlar.mjs, holat 12, 1 000 vazifa (natijalar/18-renderlar-12.txt):
tema tanlovi (Context) commit 1, render 2 — TemaProvider×1, TemaTanlov×1Bitta commit, ikki render: TemaProvider (o'z state'i) va TemaTanlov (yagona iste'molchi). App — 730 qatorli komponent, ichida 1 000 vazifali ro'yxat — umuman chizilmadi. Holat 20 dagi qayta o'lchovda ham o'sha (20-renderlar.txt).
Qaror: qiymatni useMemo ga o'rash kerak emas. Iste'molchi bitta va u tema almashganda baribir chizilishi kerak (u tanlovni ko'rsatadi). useMemo faqat kod qo'shardi. Bu «"Qayta render — yomon" mifi» dagi tartib: avval o'lchov, keyin qaror — va ba'zan qaror "hech narsa qilmaslik".
7.3 Qolgan joylar
Xuddi shu o'lchovdagi boshqa satr: e'lon o'chishi — 17 render (App va uning memo siz bolalari). E'lon state'i (useElon) App da: uni App ning 16 joyi yozadi (elonQil(…) — saqlash, o'chirish, import, eksport…). Pastga tushirib bo'lmaydi — yozuvchilar App da. 17 render esa arzon: ro'yxat memo bilan himoyalangan (useDeferredValue dagi memo(VazifaRoyxati)). Kanon unga tegmadi — to'g'ri qaror.
8. Ko'p uchraydigan xatolar
| Belgi | Sabab | Davosi |
|---|---|---|
| input yozganda butun sahifa chiziladi | input state'i App da |
state'ni input komponentiga |
| custom hook'ga chiqardim, render kamaymadi | hook state'i chaqiruvchiniki | komponentga ajrating |
children bilan ham og'ir qism chizilyapti |
element state egasining ichida yasalgan | elementni yuqorida yasang |
| provider'dagi state o'zgarsa hamma chiziladi | state App da, provider faqat qiymatni uzatadi |
provider komponenti + children |
context ostidan chiqqan komponent null oldi |
provider juda pastga tushirildi | provider'ni iste'molchilarning umumiy otasiga |
| tuzilishni o'zgartirdim, o'zgarish yo'q | komponent state'ga haqiqatan bog'liq | useDeferredValue, memo, virtualizatsiya |
9. Mashqlar
Mashqlar kurs/mashqlar/18/19-kompozitsiya/ da. Har yechimni «Ishga tushir» bilan sinang.
1-mashq (oson): qaysi usul?
- Qidiruv maydoni state'i
Appda, faqat maydon ishlatadi: - Modal oynaning
openstate'i og'ir forma atrofida (<dialog open>ichida forma): - Soat har soniya yangilanadi,
Appichida yozilgan:
Yechim
Birinchisida state'ni ishlatadigan yagona joy bor — state shu yerga ko'chadi. Ikkinchisida state og'ir qismni o'raydi — o'ram komponenti forma'ni children sifatida oladi. Uchinchisi — birinchining varianti: tez yangilanadigan kichik qism o'z komponentiga chiqadi, state bilan birga.
2-mashq (o'rta): buyurtma vaqti
App da now state'i (soat) va og'ir OrderTable. «Tik» tugmasi soniyani oshiradi (haqiqiy ilovada — setInterval). Hozir OrderTable har «Tik» da chiziladi. Kodni qayta tuzing: OrderTable faqat bir marta chizilsin, soat esa yangilansin. Kutilgan konsol — pastda.
import { useState } from "react";
function OrderTable() {
console.log("OrderTable chizildi");
return <p>Buyurtmalar: 12 ta</p>;
}
function App() {
const [now, setNow] = useState(0);
return (
<main>
<p>Soniya: {now}</p>
<button onClick={() => setNow(now + 1)}>Tik</button>
<OrderTable />
</main>
);
}Konsolda:
OrderTable chizildi
OrderTable chizildi
OrderTable chizildiYechim
import { useState } from "react";
function OrderTable() {
console.log("OrderTable chizildi");
return <p>Buyurtmalar: 12 ta</p>;
}
function Clock() {
const [now, setNow] = useState(0);
console.log("Clock:", now);
return (
<>
<p>Soniya: {now}</p>
<button onClick={() => setNow(now + 1)}>Tik</button>
</>
);
}
function App() {
return (
<main>
<Clock />
<OrderTable />
</main>
);
}Konsolda:
Clock: 0
OrderTable chizildi
Clock: 1
Clock: 2Ekranda:
Soniya: 2
Tik
Buyurtmalar: 12 tanow va uni ishlatadigan ikki element Clock ga ko'chdi. App endi state'siz — u faqat bir marta chiziladi, OrderTable ham. Haqiqiy setInterval bilan ham xuddi shunday: effekt Clock ichida (useEffect III: cleanup).
3-mashq (qiyin): retsept paneli
Retsept paneli: sarlavha, «Rang» tugmasi (highlight state'i sarlavhani qizil qiladi) va ichida og'ir Recipe. Hozir hammasi bitta komponentda va Recipe har bosishda chiziladi. Talab: qayta ishlatiladigan Panel komponentini yozing (title va children props). Recipe panel ichida qolsin, lekin «Rang» bosilganda chizilmasin. Faqat children naqshi bilan, memo siz.
import { useState } from "react";
function Recipe() {
console.log("Recipe chizildi");
return <p>Osh: guruch, sabzi, go'sht</p>;
}
function App() {
const [highlight, setHighlight] = useState(false);
return (
<section>
<h2 style={{ color: highlight ? "red" : "black" }}>Retsept</h2>
<button onClick={() => setHighlight(!highlight)}>Rang</button>
<Recipe />
</section>
);
}Yechim
import { useState } from "react";
function Recipe() {
console.log("Recipe chizildi");
return <p>Osh: guruch, sabzi, go'sht</p>;
}
function Panel({ title, children }) {
const [highlight, setHighlight] = useState(false);
console.log("Panel:", highlight);
return (
<section>
<h2 style={{ color: highlight ? "red" : "black" }}>{title}</h2>
<button onClick={() => setHighlight(!highlight)}>Rang</button>
{children}
</section>
);
}
function App() {
return (
<Panel title="Retsept">
<Recipe />
</Panel>
);
}Konsolda:
Panel: false
Recipe chizildi
Panel: true
Panel: falsehighlight endi Panel da, <Recipe /> esa App da yasaladi va children bo'lib keladi. Panel chizilganda children — o'sha element, Recipe tegilmaydi. Bonus: Panel endi qayta ishlatiladigan komponent — title va children bilan istalgan mazmunni o'raydi. Kompozitsiya ko'pincha shunday: tezlik bilan birga yaxshiroq API ham beradi (Compound komponentlar darsida davomi).
4-mashq: vazifalar — kim state'ni o'qiydi?
vazifalar ning App.tsx ida (holat 20) har useState/useReducer/useOptimistic uchun yozing: uni qaysi komponentlar o'qiydi va qaysilar yozadi. Qaysi biri pastga tushishi mumkin edi? e'lon haqidagi «Qolgan joylar» bo'limidagi xulosani o'zingiz tekshiring: elonQil( necha joyda chaqiriladi? Kod o'zgartirmang.
Yechim
grep -c "elonQil(" src/App.tsx — kanonda (holat 20) 16 qator, har birida bitta chaqiruv. Yozuvchilar App ichidagi ishlovchilar, o'quvchi — Bildirishnoma. Bunday state'ni pastga tushirib bo'lmaydi: yozuvchilarni ham ko'chirish kerak bo'lardi. Muqobil — tashqi do'kon (useSyncExternalStore, useSyncExternalStore), shunda faqat Bildirishnoma chiziladi. Lekin 17 render (1 commit) — o'lchovda sezilmaydi, murakkablik esa oshadi. Tahlilning o'zi — mashqning maqsadi: har state uchun "kim o'qiydi?" savoliga javob.
10. Real ishda
- Layout komponentlari:
Layout,Card,Modal,Drawer— deyarli hammasichildrenyoki slot props bilan yoziladi: o'ram o'z holatini (ochiq/yopiq, rang) boshqaradi, mazmun esa tashqaridan keladi. - Provider'lar: Next.js va boshqa freymvorklarda
<Providers>{children}</Providers>naqshi standart — aynan shu sababdan. - Forma kutubxonalari: React Hook Form kabi kutubxonalar input state'ini input yonida saqlaydi (uncontrolled) — butun forma har harfda chizilmasligi uchun (keyingi qismlarda).
- Intervyu savollari: "
memosiz renderni qanday kamaytirasiz?", "Negachildrenqayta chizilmaydi?", "State colocation nima?", "Provider'ni qayerga qo'yasiz?".
Xulosa
memodan oldin — tuzilish: "ota chizildi" sababini yo'qotish uni to'xtatishdan arzon.- State colocation: state'ni uni o'qiydigan eng pastki komponentga; tez qismni alohida komponentga ajrating (hook'ga emas).
childrenorqali uzatish: og'ir element state egasidan yuqorida yasaladi — o'ram chizilganda u o'sha obyekt, React tegmaydi.- Provider —
childrenli komponent: tema almashganda faqat provider va iste'molchilar chiziladi. vazifalar: tema — 1 commit, 2 render (Appumuman chizilmadi),useMemokerak emas; e'lon state'i 16 joyda yoziladi — pastga tushmaydi, 17 render esa arzon.
Keyingi dars: memo, useMemo, useCallback: qachon va qanday — kompozitsiya yetmaganda: vazifalar ro'yxatida 18 056 → 68 render.
Manbalar
- React:
memo— "Minimizing props changes" — react.dev/reference/react/memo - React: "Passing JSX as children" — react.dev/learn/passing-props-to-a-component
- Dan Abramov, "Before You memo()" (2021-02-23) — overreacted.io/before-you-memo
- Kanon:
sinov/18/QADAMLAR.md(#16–#20),natijalar/18-renderlar-12.txt,natijalar/20-renderlar.txt
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!