Mundarija (25)
- Bu darsda
- 1. Nega bu kerak?
- 2. Toza komponent: ikki qoida
- 2.1 Qoidalar
- 2.2 Toza bo'lmagan komponent
- 3. StrictMode tuzoqni fosh qiladi
- 3.1 Ikki marta chaqiruv
- 3.2 Brauzer konsolida
- 3.3 StrictMode yana nimani tekshiradi
- 4. Render paytidagi side effect'lar
- 4.1 Props'dagi massivni o'zgartirish
- 4.2 Har chaqiruvda boshqa natija: vaqt va tasodif
- 4.3 DOM'ga va tashqi tizimlarga tegish
- 4.4 Lokal mutatsiya — ruxsat
- 5. Linter toza emasni topadi
- 6. Render va commit — bir qadam oldinga
- 7. Ko'p uchraydigan xatolar
- 8. Mashqlar
- 1-mashq (oson): toza yoki yo'q?
- 2-mashq (o'rta): buzilgan menyu
- 3-mashq (qiyin): mehmon raqamlari — toza usulda
- 4-mashq: vazifalar ga nazar
- 9. Real ishda
- Xulosa
- Manbalar
Pure komponentlar va render qoidasi: React nega StrictMode'da ikki marta chaqiradi
Qisqacha: React komponenti toza (pure) bo'lishi kerak: bir xil props bilan har doim bir xil JSX qaytarsin. Chizish paytida u tashqaridagi hech narsani o'zgartirmasin — global o'zgaruvchi, props'dagi massiv,
document.titleyoki server. Sababi: komponentni React o'zi, xohlagan paytda va xohlagancha marta chaqiradi. Ish bajarish (saqlash, yuborish, DOM'ga tegish) — hodisa ishlovchilarida yoki effektlarda. Komponent ichida yangi yaratilgan massivni o'zgartirish esa mumkin. Dev rejimda<StrictMode>har komponentni ataylab ikki marta chaqirib, toza emasini fosh qiladi.
Bu darsda
- Toza komponentning ikki qoidasini aytib bera olasiz va toza emasini ko'rib taniysiz.
- Render paytidagi side effect qanday xatoga olib kelishini jonli ko'rasiz.
- Qaysi mutatsiya taqiqlangan, qaysi biri (lokal) ruxsat etilganini ajratasiz.
- StrictMode nima qilishini va nega konsolda yozuvlar ikki marta chiqishini tushuntira olasiz.
- Toza bo'lmagan kodni
eslint-plugin-react-hooksbilan ushlaysiz.
Oldin bilishingiz kerak: Pure funksiya va side effect, Props: komponentga ma'lumot uzatish, Ro'yxatlarni render qilish va key.
1. Nega bu kerak?
Pure funksiya va side effect darsida ikki xil funksiyani ko'rgandik. Toza funksiya — bir xil kirishga doim bir xil natija va tashqariga ta'sirsiz: narxniHisobla(2, 35000) doim 70000. Toza bo'lmagani — tashqaridagi narsani o'zgartiradi yoki tashqi narsaga qarab har safar boshqa natija beradi. O'sha darsda React'ga va'da bergan edik: "komponentlar toza bo'lishi shart".
Nega aynan React'da bu shunchalik muhim? Chunki komponentni siz chaqirmaysiz. Komponentlar darsida ko'rdik: <Cup /> faqat "buyurtma qog'ozi", funksiyani React chaqiradi. Qachon chaqirishni ham React hal qiladi. Ota qayta chizilsa — chaqiradi. Ba'zan chizishni boshlab, to'xtatib, qaytadan chaqiradi. Dev rejimda tekshiruv uchun ikki marta chaqiradi. Komponent har chaqiruvda nimanidir o'zgartirsa, natija "necha marta chaqirilgani"ga bog'liq bo'lib qoladi.
Hayotiy o'xshatish: oshpaz va retsept. Retsept bo'yicha osh pishirish — toza: bir xil masalliq, bir xil osh. Lekin oshpaz har safar retseptni o'qiganda omborga borib, bitta qop guruch ochsa-chi? "Retseptni ikki marta o'qib qo'ydim" — omborda ikki qop ochilib yotadi. Retseptni o'qish zararsiz bo'lishi kerak. Omborga borish — alohida ish, aniq paytda qilinadi.
2. Toza komponent: ikki qoida
2.1 Qoidalar
- Bir xil kirish — bir xil natija. Bir xil props (keyinroq — state va context) bilan komponent doim bir xil JSX qaytaradi. Bu xususiyat idempotentlik deyiladi: necha marta chaqirsangiz ham, natija o'sha.
- Render paytida tashqariga ta'sir yo'q. Komponent chaqirilgunga qadar mavjud bo'lgan narsani o'zgartirmaydi: global o'zgaruvchi, props,
document,localStorage, server.
Siz yozgan komponentlarning deyarli hammasi allaqachon toza:
function OrderLine({ dish, price, count }) {
const total = price * count;
return (
<li>
{dish} × {count} = {total} so'm
</li>
);
}
function App() {
return (
<ul>
<OrderLine dish="Osh" price={35000} count={2} />
<OrderLine dish="Osh" price={35000} count={2} />
</ul>
);
}Ekranda:
Osh × 2 = 70000 so'm
Osh × 2 = 70000 so'mtotal — komponent ichida hisoblangan yangi o'zgaruvchi, tashqariga ta'siri yo'q. Bir xil props — bir xil qator. Buni UI = f(state) formulasining "f" qismi deb tasavvur qiling: matematik funksiya kabi.
2.2 Toza bo'lmagan komponent
Sardor «Bahor» choyxonasi uchun piyolalarga raqam qo'ymoqchi bo'ldi: har piyola — keyingi mehmon. Raqamni global o'zgaruvchida saqladi:
let guest = 0;
function Cup() {
guest = guest + 1; // ❌ tashqaridagi o'zgaruvchi o'zgaryapti
return <p>Piyola: {guest}-mehmon uchun</p>;
}
function App() {
return (
<>
<Cup />
<Cup />
<Cup />
</>
);
}Ekranda:
Piyola: 1-mehmon uchun
Piyola: 2-mehmon uchun
Piyola: 3-mehmon uchunTo'g'ri ko'rinadi. Lekin bu tasodif: natija Cup necha marta chaqirilganiga bog'liq. Bitta <Cup /> — bitta chaqiruv bo'lsa, raqamlar to'g'ri. React esa bunday va'da bermaydi. Ota qayta chizilsa, uchala Cup yana chaqiriladi — va raqamlar 4, 5, 6 bo'lib ketadi, mehmonlar esa o'sha uchta.
3. StrictMode tuzoqni fosh qiladi
3.1 Ikki marta chaqiruv
Birinchi React loyiha darsida main.tsx dagi <StrictMode> ni ko'rgandik va o'lchagandik: dev rejimda komponent ikki marta chaqiriladi. Endi nega ekanini ko'ramiz. O'sha Cup, lekin StrictMode ichida:
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
let guest = 0;
function Cup() {
guest = guest + 1;
console.log("Cup chaqirildi, guest =", guest);
return <p>Piyola: {guest}-mehmon uchun</p>;
}
createRoot(document.getElementById("root")).render(
<StrictMode>
<Cup />
<Cup />
<Cup />
</StrictMode>
);Konsolda:
Cup chaqirildi, guest = 1
Cup chaqirildi, guest = 2
Cup chaqirildi, guest = 3
Cup chaqirildi, guest = 4
Cup chaqirildi, guest = 5
Cup chaqirildi, guest = 6Ekranda:
Piyola: 2-mehmon uchun
Piyola: 4-mehmon uchun
Piyola: 6-mehmon uchunUch komponent — olti chaqiruv. React har birini ikki marta chaqirdi va ikkinchi natijani chizdi. Toza komponentda ikkala natija bir xil bo'lardi va siz hech narsani sezmasdingiz. Cup esa har chaqiruvda guest ni o'zgartirdi — ekranda 2, 4, 6. Xato darhol ko'rinadi.
| Chaqiruv | guest (oldin → keyin) |
Natija |
|---|---|---|
| 1-Cup, birinchi | 0 → 1 | tashlab yuboriladi |
| 1-Cup, ikkinchi | 1 → 2 | "2-mehmon" — chiziladi |
| 2-Cup, birinchi | 2 → 3 | tashlab yuboriladi |
| 2-Cup, ikkinchi | 3 → 4 | "4-mehmon" — chiziladi |
StrictMode xatoni yaratmaydi — u bor xatoni ko'rinadigan qiladi. Production'da komponent bir marta chaqiriladi va 1, 2, 3 chiqadi. Lekin ertaga ota qayta chizilganda yoki React chizishni to'xtatib qayta boshlaganda, o'sha xato production'da ham chiqadi — kutilmagan joyda va qayta takrorlab bo'lmaydigan holda.
3.2 Brauzer konsolida
Brauzerda (React 19) ikkinchi chaqiruvdagi console.log lar xiraroq rangda chiqadi — "bu StrictMode'ning tekshiruv chaqiruvi" degani. Saytdagi natija oynasi esa ularni oddiy ko'rinishda chiqaradi. Muhimi: ikki marta chiqqan log — xato emas, tekshiruv. Xato — ikki chaqiruvning natijasi farq qilishi.
Diqqat: "Konsolda hamma narsa ikki marta chiqyapti" deb
StrictModeni olib tashlamang (Birinchi React loyiha dagi maslahat). U topgan xato baribir bor — faqat yashirinadi.
3.3 StrictMode yana nimani tekshiradi
| Tekshiruv | Nimani ushlaydi | Qaysi darsda |
|---|---|---|
| Komponentni ikki marta chaqirish | render paytidagi side effect | shu dars |
| Effektlarni ikki marta ulash | tozalanmagan obuna, taymer | Effekt hayot sikli va StrictMode |
| Ref callback'larni ikki marta | tozalanmagan DOM ishlari | useRef II |
| Eskirgan API'lar | eski usulda yozilgan kod | React 18 dan 19 ga |
Hammasi faqat dev rejimda. Production build'da StrictMode hech narsa qilmaydi va tezlikka ta'sir qilmaydi. vazifalar da ham ikkala React oroli — #izoh va ro'yxat — <StrictMode> ichida chiziladi.
Tekshirib ko'ring: StrictMode ichidagi toza
OrderLine(yuqoridagi) har chizishda necha marta chaqiriladi? Ekranda farq bormi?
Javob
Dev rejimda — ikki marta, production'da — bir marta. Ekranda farq yo'q: ikkala chaqiruv ham 70000 hisoblaydi va bir xil JSX qaytaradi. Toza komponent uchun ikki marta chaqiruv bilinmaydi — aynan shuning uchun StrictMode bu usulni tanlagan.
4. Render paytidagi side effect'lar
4.1 Props'dagi massivni o'zgartirish
Eng yashirin xato — props'dagi massiv yoki obyektni joyida o'zgartirish. Bir menyu ikki komponentga berilgan: biri alifbo bo'yicha, biri asl tartibda ko'rsatadi:
const menu = ["Osh", "Manti", "Choy"];
function SortedMenu({ items }) {
items.sort(); // ❌ ota komponentning massivi o'zgaradi
return <p>Alifbo: {items.join(", ")}</p>;
}
function OriginalMenu({ items }) {
return <p>Asl tartib: {items.join(", ")}</p>;
}
function App() {
return (
<>
<SortedMenu items={menu} />
<OriginalMenu items={menu} />
</>
);
}Ekranda:
Alifbo: Choy, Manti, Osh
Asl tartib: Choy, Manti, Osh"Asl tartib" buzildi. Sababi: sort() massivni joyida o'zgartiradi (sort va taqqoslash funksiyasi). Bu yerda esa items va menu — bitta massiv (havola semantikasi). Ya'ni SortedMenu o'zining props'ini emas, butun ilovaning ma'lumotini buzdi. Props darsida React props obyektini muzlatishini ko'rgandik, lekin u sayoz muzlatish. Ya'ni props.items = … deb yozib bo'lmaydi, massivning ichini esa o'zgartirish mumkin. Tuzatish — nusxa bilan ishlaydigan metod:
const menu = ["Osh", "Manti", "Choy"];
function SortedMenu({ items }) {
const sorted = items.toSorted(); // ✅ yangi massiv
return <p>Alifbo: {sorted.join(", ")}</p>;
}
function OriginalMenu({ items }) {
return <p>Asl tartib: {items.join(", ")}</p>;
}
function App() {
return (
<>
<SortedMenu items={menu} />
<OriginalMenu items={menu} />
</>
);
}Ekranda:
Alifbo: Choy, Manti, Osh
Asl tartib: Osh, Manti, ChoyRo'yxatlar va key darsida toSorted ni tanlaganimizning sababi shu edi.
4.2 Har chaqiruvda boshqa natija: vaqt va tasodif
Qoidaning birinchi qismi — "bir xil kirish — bir xil natija" — boshqacha ham buziladi:
function LuckyDish() {
// ❌ har chaqiruvda boshqa taom
const index = Math.floor(Math.random() * 3);
return <p>Bugungi taklif: {["Osh", "Manti", "Somsa"][index]}</p>;
}Bu komponent tashqariga hech narsa yozmaydi, lekin baribir toza emas. Props o'zgarmasa ham, har qayta chizishda taklif almashib turadi. Mijoz menyuni o'qiyotganda "Osh" "Manti" ga aylanib qoladi. Date.now() va new Date() ham shunday: natija chaqiruv vaqtiga bog'liq. Serverda oldindan chizilgan sahifada (SSR — server-side rendering, Next.js qismida) bu yana bir xato beradi: server bir taomni chizadi, brauzer boshqasini.
Yechim — tasodifiy yoki vaqtga bog'liq qiymatni render'dan tashqarida bir marta olish va props yoki state bilan berish. Masalan, "bugungi taklif" serverdan keladi yoki ilova ochilganda bir marta tanlanadi.
4.3 DOM'ga va tashqi tizimlarga tegish
function OrdersPage({ count }) {
document.title = `Buyurtmalar (${count})`; // ❌ render paytida DOM
localStorage.setItem("oxirgi", String(count)); // ❌ saqlash
fetch("/api/korildi", { method: "POST" }); // ❌ serverga so'rov
return <h1>Buyurtmalar: {count}</h1>;
}Uch qatorning uchalasi ham "ish": sahifa sarlavhasini o'zgartirish, saqlash, serverga yozish. StrictMode'da har biri ikki marta bajariladi. Production'da esa React necha marta chizsa, shuncha marta — ya'ni oldindan aytib bo'lmaydi. Server bir ko'rishni uch marta yozib qo'yishi mumkin.
Bunday ishlar qayerda bajariladi?
flowchart LR
E["Hodisa: bosish, yozish"] --> H["Ishlovchi: ish bajaradi"]
H --> S["Holat o'zgaradi"]
S --> R["Render: faqat hisoblaydi"]
R --> C["React DOM'ni yangilaydi"]
C -. "tashqi tizim bilan sinxron" .-> F["Effekt"]Diagrammani chapdan o'qing. Ish — hodisa ishlovchisida: tugma bosildi → saqlash, yuborish (Hodisalarni boshqarish). Render faqat hisoblaydi. "Ekran chizilgandan keyin tashqi tizimni moslash" (sahifa sarlavhasi, obuna) — effektda (useEffect I). Render o'rtada — u toza qoladi.
4.4 Lokal mutatsiya — ruxsat
Qoida "hech narsani o'zgartirma" emas, "mavjud narsani o'zgartirma". Komponent ichida shu chaqiruvda yaratilgan massiv yoki obyektni o'zgartirish — mutlaqo toza:
function Receipt({ items }) {
const lines = []; // shu chaqiruvda yaratildi
let total = 0;
for (const item of items) {
total += item.price * item.count;
lines.push(
<li key={item.id}>
{item.dish} × {item.count}
</li>
);
}
return (
<>
<ul>{lines}</ul>
<p>Jami: {total} so'm</p>
</>
);
}
function App() {
const order = [
{ id: 1, dish: "Osh", price: 35000, count: 2 },
{ id: 2, dish: "Ko'k choy", price: 5000, count: 1 },
];
return <Receipt items={order} />;
}Ekranda:
Osh × 2
Ko'k choy × 1
Jami: 75000 so'mlines.push va total += — o'zgartirish, lekin lines va total har chaqiruvda noldan yaratiladi. Tashqaridan ularni hech kim ko'rmaydi. Ikki marta chaqirilsa — ikki marta bir xil massiv va bir xil son. Bu lokal mutatsiya (local mutation). vazifalar dagi BelgilanganMatn ham aynan shunday ishlaydi (Shartli render darsida yozganmiz): const qismlar = [] va qismlar.push(…).
| O'zgartirilayotgan narsa | Qachon yaratilgan | Toza? |
|---|---|---|
const lines = [] → push |
shu chaqiruvda | ha |
props.items → sort() |
ota komponentda | yo'q |
modul darajasidagi let guest |
fayl yuklanganda | yo'q |
document.title |
brauzerda | yo'q |
Tekshirib ko'ring:
function Menu({ items }) { const copy = [...items]; copy.sort(); return <p>{copy.join(", ")}</p>; }— toza komponentmi?
Javob
Ha. copy — shu chaqiruvda yaratilgan yangi massiv (spread — sayoz nusxa). Uni saralash — lokal mutatsiya, items ga tegmaydi. Bu toSorted() ning eski yozilishi — ikkalasi ham to'g'ri. Faqat bir narsani eslang: sayoz nusxada ichidagi obyektlar o'sha-o'sha. copy[0].price = 0 yozilsa, otaning obyekti o'zgaradi — bu State III darsining mavzusi.
5. Linter toza emasni topadi
StrictMode xatoni ishga tushirgandan keyin ko'rsatadi. Linter esa kod yozilayotgandayoq ogohlantiradi. vazifalar ga ulangan eslint-plugin-react-hooks 7.1.1 da toza bo'lmagan kod uchun bir nechta qoida bor. Ular React Compiler'ning tahliliga asoslangan (React Compiler — 18-qismda). Bitta faylda to'rtta komponentni tekshirdik: Cup, LuckyDish, SortedMenu va document.title yozadigan Title:
npx eslint Toza.jsxChiqish (ESLint 10.12.0; kod parchalari olib tashlangan). Har xato uch qismdan iborat: boshida qator:ustun va qisqa sarlavha, o'rtada izoh, oxirida qoida nomi (react-hooks/…). Avval qoida nomlariga qarang:
4:3 error Error: Cannot reassign variables declared outside of the component/hook
Variable `guest` is declared outside of the component/hook. Reassigning this value during render is a form of side effect, which can cause unpredictable behavior depending on when the component happens to re-render. If this variable is used in rendering, use useState instead. Otherwise, consider updating it in an effect.
react-hooks/globals
9:28 error Error: Cannot call impure function during render
`Math.random` is an impure function. Calling an impure function can produce unstable results that update unpredictably when the component happens to re-render.
react-hooks/purity
19:3 error Error: This value cannot be modified
Modifying a variable defined outside a component or hook is not allowed. Consider using an effect.
react-hooks/immutability
✖ 3 problems (3 errors, 0 warnings)Uchta qoida, uchta tarjima:
react-hooks/globals— "Komponentdan tashqarida e'lon qilingan o'zgaruvchiga render paytida yangi qiymat yozish — side effect. Komponent qachon qayta chizilishiga qarab natija kutilmagan bo'ladi. Ekranda ishlatilsa —useStateishlating, aks holda effektda yangilang."react-hooks/purity— "Math.random— toza bo'lmagan funksiya. Uni render paytida chaqirish beqaror natija beradi."react-hooks/immutability— "Komponentdan tashqarida aniqlangan narsani o'zgartirish mumkin emas. Effekt ishlating." (document.title.)
E'tibor bering: to'rtinchi komponent — SortedMenu dagi items.sort() — xato bermadi. Linter props ichidagi massiv metodining joyida o'zgartirishini har doim ham ko'ra olmaydi. Shuning uchun uch qatlam birga ishlaydi: siz bilgan qoida, linter va StrictMode.
6. Render va commit — bir qadam oldinga
"Chizish" ni React ikki bosqichga bo'ladi. Buni bilish toza bo'lish nega muhimligini oxirigacha tushuntiradi:
sequenceDiagram
participant T as Sabab
participant R as Render
participant C as Commit
T->>R: birinchi chizish yoki holat o'zgardi
R->>R: komponentlarni chaqiradi, JSX yig'adi
R->>C: yangi va eski daraxt farqi
C->>C: DOM'ni o'zgartiradi- Render — React komponentlaringizni chaqiradi va yangi daraxtni hisoblaydi. Bu faqat hisob-kitob: hali DOM'ga tegilmagan. React bu bosqichni to'xtatishi, tashlab yuborishi, qayta boshlashi mumkin. Shuning uchun u toza bo'lishi shart.
- Commit — React farqni DOM'ga yozadi. Bu bosqichni React o'zi boshqaradi va u bir marta, oxirigacha bajariladi.
Toza komponentlar React'ga erkinlik beradi: ishni bo'laklarga bo'lish, muhimini oldinga o'tkazish, keraksizini tashlab yuborish (Concurrent rendering). Natijani eslab qolib, qayta hisoblamaslik ham mumkin bo'ladi (memo). Bularning hammasi bitta shartga tayanadi: komponentni chaqirish zararsiz. To'liq zanjir — Render va commit darsida.
7. Ko'p uchraydigan xatolar
| Belgi | Sabab | Davosi |
|---|---|---|
| dev'da raqamlar 2, 4, 6 | render paytida global hisoblagich | ma'lumotdan hisoblang yoki state |
| boshqa komponentda tartib buzildi | props massivida sort(), reverse(), push() |
toSorted(), spread nusxa |
| har chizishda boshqa qiymat | renderda Math.random(), Date.now() |
render'dan tashqarida bir marta |
| so'rov ikki marta ketdi | renderda fetch, localStorage |
hodisada yoki effektda |
| "konsolda ikki marta" | StrictMode — xato emas | natijalar farq qilmasa — hammasi joyida |
Cannot reassign variables declared outside |
react-hooks/globals |
yuqoridagi birinchi qator |
8. Mashqlar
Mashqlar kurs/mashqlar/17/10-toza-komponent/ da. Har yechimni «Ishga tushir» bilan sinang.
1-mashq (oson): toza yoki yo'q?
Har komponent uchun "toza" yoki "toza emas" deb yozing va sababini ayting.
// A
function Price({ value }) {
return <b>{value.toLocaleString("uz-UZ")} so'm</b>;
}
// B
let renders = 0;
function Counter() {
renders++;
return <p>{renders}</p>;
}
// C
function TagList({ tags }) {
const sorted = [...tags].sort();
return <p>{sorted.join(" ")}</p>;
}
// D
function Greeting({ name }) {
console.log("Greeting:", name);
return <h2>Salom, {name}!</h2>;
}
// E
function Clock() {
return <p>{new Date().toLocaleTimeString()}</p>;
}- A:
- B:
- E:
Yechim
- A — toza. Faqat props'dan hisoblaydi, hech narsani o'zgartirmaydi.
- B — toza emas. Modul darajasidagi
rendersni o'zgartiradi — StrictMode'da 2, 4, … chiqadi. - C — toza.
[...tags]— yangi massiv, uni saralash — lokal mutatsiya. - D — toza (amalda).
console.log— texnik jihatdan side effect, lekin u faqat ishlab chiqishda kuzatish uchun va ilova holatini o'zgartirmaydi. React ham buni kutadi: StrictMode'ning ikkinchi logi aynan shuning uchun xira chiqadi. - E — toza emas. Natija vaqtga bog'liq — bir xil props (props yo'q) bilan har chaqiruvda boshqa matn. Soat kerak bo'lsa, vaqt state'da saqlanadi va taymer effektda yangilaydi (useEffect I).
2-mashq (o'rta): buzilgan menyu
Quyidagi ilovada ikki komponent bitta menu ni ishlatadi. CheapestFirst narx bo'yicha arzonidan boshlab ko'rsatadi, TopDish esa menyuning birinchi taomini "Kun taomi" deb e'lon qiladi. Kun taomi osh bo'lishi kerak edi, lekin ekranda "Ko'k choy" chiqyapti. Xatoni toping va tuzating: CheapestFirst ning natijasi o'zgarmasin, "Kun taomi: Osh" chiqsin.
const menu = [
{ id: 1, name: "Osh", price: 35000 },
{ id: 2, name: "Manti", price: 30000 },
{ id: 3, name: "Ko'k choy", price: 5000 },
];
function CheapestFirst({ items }) {
items.sort((a, b) => a.price - b.price);
return (
<ol>
{items.map((d) => (
<li key={d.id}>{d.name}</li>
))}
</ol>
);
}
function TopDish({ items }) {
return <p>Kun taomi: {items[0].name}</p>;
}
function App() {
return (
<>
<CheapestFirst items={menu} />
<TopDish items={menu} />
</>
);
}Ekranda:
Ko'k choy
Manti
Osh
Kun taomi: Ko'k choyIshora: «Props'dagi massivni o'zgartirish» bo'limi.
Yechim
const menu = [
{ id: 1, name: "Osh", price: 35000 },
{ id: 2, name: "Manti", price: 30000 },
{ id: 3, name: "Ko'k choy", price: 5000 },
];
function CheapestFirst({ items }) {
const sorted = items.toSorted((a, b) => a.price - b.price);
return (
<ol>
{sorted.map((d) => (
<li key={d.id}>{d.name}</li>
))}
</ol>
);
}
function TopDish({ items }) {
return <p>Kun taomi: {items[0].name}</p>;
}
function App() {
return (
<>
<CheapestFirst items={menu} />
<TopDish items={menu} />
</>
);
}Ekranda:
Ko'k choy
Manti
Osh
Kun taomi: Oshsort menu ning o'zini o'zgartirgandi — TopDish chizilganda massivning birinchi elementi allaqachon ko'k choy edi. Xato TopDish da ko'rindi, lekin sababi CheapestFirst da. Toza bo'lmagan komponent xatosining eng yomon tomoni shu: belgi bir joyda, sabab boshqa joyda. toSorted yangi massiv qaytaradi va menu ga tegmaydi.
3-mashq (qiyin): mehmon raqamlari — toza usulda
Cup misolini toza qiling. Talablar:
- global
guesto'zgaruvchisi bo'lmasin; Cupraqamni props'dan olsin:<Cup guest={…} />;Appmehmonlar massividan (["Ali", "Malika", "Bobur"]) piyolalar chizsin, raqam —mapdagi indeksdan + 1, ismi ham chiqsin;App<StrictMode>ichida chizilsin vaCupichidaconsole.logbo'lsin — StrictMode'da ham raqamlar 1, 2, 3 qolishini ko'ring.
Bu yerda key sifatida ism yetadi (ismlar takrorlanmaydi). Indeksni esa faqat raqam uchun ishlatamiz — key uchun emas.
Piyola №1 — Ali
Piyola №2 — Malika
Piyola №3 — BoburYechim
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
function Cup({ guest, name }) {
console.log("Cup:", guest);
return (
<p>
Piyola №{guest} — {name}
</p>
);
}
function App() {
const guests = ["Ali", "Malika", "Bobur"];
return (
<>
{guests.map((name, index) => (
<Cup key={name} guest={index + 1} name={name} />
))}
</>
);
}
createRoot(document.getElementById("root")).render(
<StrictMode>
<App />
</StrictMode>
);Konsolda:
Cup: 1
Cup: 1
Cup: 2
Cup: 2
Cup: 3
Cup: 3Ekranda:
Piyola №1 — Ali
Piyola №2 — Malika
Piyola №3 — BoburHar Cup ikki marta chaqirildi (StrictMode) — va ikkala marta ham bir xil raqam. Raqam endi tashqi hisoblagichdan emas, ma'lumotdan (massivdagi o'rindan) kelib chiqadi. Bu — UI = f(state): ekran ma'lumotning funksiyasi, chaqiruvlar soniga bog'liq emas.
4-mashq: vazifalar ga nazar
Bu darsda vazifalar kodi o'zgarmaydi. Ro'yxatlar va key darsida commit qilingan fayllarni oching va uchta savolga javob bering:
BelgilanganMatn.tsxdaqismlar.push(...)bor. Bu toza komponent qoidasini buzadimi?render.tsxdaroyxatIldizi.render(...)ichidakorinadiganlar()chaqiriladi — u holatdan filtrlangan va saralangan massiv qaytaradi. Agar uholat.vazifalar.sort(...)qilganda edi, qanday xavf bo'lardi?VazifaQatorinega globalholat.tahrirIdga qaramaydi,tahrirdaprops'ini oladi?
Yechim
- Yo'q.
qismlarhar chaqiruvda[]bilan yangidan yaratiladi — bu lokal mutatsiya. StrictMode ikki marta chaqirsa — ikki marta bir xil bo'laklar. sortjoyida o'zgartiradi — har chizishda asl ro'yxat tartibi buzilardi. Saqlash, eksport va server sinxroni ham boshqa tartibni ko'rardi. Shuning uchunkorinadiganlar()yangi massiv qaytaradi (filtr va saralash nusxada). Aslholat.vazifalaresa faqat o'qiladi. State III darsida bureadonlybilan majburiy bo'ladi.- Global holatni o'qigan komponent "bir xil props — bir xil natija" qoidasini buzadi: props o'zgarmasa ham, global qiymat o'zgarib qolishi mumkin. Props bilan esa natija faqat kirishga bog'liq — komponentni test qilish ham oson:
VazifaRoyxati.test.tsxuni hech qanday global holatsiz chizadi.
9. Real ishda
- StrictMode — Vite, Next.js va boshqa shablonlarda sukut bo'yicha yoqilgan. Uni o'chirgan kod kod ko'rigida savol uyg'otadi.
- React Compiler (18-qismda) faqat toza komponentlarni xavfsiz optimallashtira oladi. Toza bo'lmagan kodni kompilyator "o'tkazib yuboradi" yoki buzib qo'yadi. Shuning uchun
react-hookslint qoidalari ham kompilyator tahliliga asoslangan. - SSR va hydration (serverdan kelgan tayyor HTML'ni brauzerda React "jonlantirishi") — serverda va brauzerda bir xil komponent bir xil natija berishi shart. Renderdagi
Math.random()yokiDate.now()— "hydration mismatch" xatosining eng ko'p uchraydigan sababi. - Intervyu savollari: "Pure komponent nima?", "Nega StrictMode komponentni ikki marta chaqiradi?", "Komponent ichida massivni
pushqilsa bo'ladimi?", "Side effect'ni qayerga yozasiz?".
Xulosa
- Toza komponent: bir xil props — bir xil JSX, va render paytida tashqaridagi hech narsa o'zgarmaydi.
- Render paytida global o'zgaruvchi, props ichidagi massiv,
documentva tashqi tizimlarga tegmang;Math.random,Date.nowham natijani beqaror qiladi. - Shu chaqiruvda yaratilgan massiv yoki obyektni o'zgartirish (lokal mutatsiya) — ruxsat.
- StrictMode dev'da har komponentni ikki marta chaqiradi: toza komponentda farq bilinmaydi, toza bo'lmaganida xato ochiladi.
- Ish — hodisa ishlovchisida, tashqi tizim bilan sinxronlash — effektda; render faqat hisoblaydi.
react-hooks/globals,purity,immutabilityqoidalari ko'p holatni yozish paytidayoq ushlaydi — lekin hammasini emas.
Keyingi dars: Hodisalarni boshqarish — ish bajariladigan joy: onClick, onChange, onSubmit va vazifalar qatorlaridagi tugmalarni React'ga o'tkazamiz.
Manbalar
- React: "Keeping Components Pure" — react.dev/learn/keeping-components-pure
- React: "Components and Hooks must be pure" — react.dev/reference/rules/components-and-hooks-must-be-pure
- React:
<StrictMode>— react.dev/reference/react/StrictMode - React: "Render and Commit" — react.dev/learn/render-and-commit
eslint-plugin-react-hooks:globals,purity,immutabilityqoidalari — react.dev/reference/eslint-plugin-react-hooks
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!