Mundarija (27)
- Bu darsda
- 1. Nega bu kerak?
- 2. children — teglar orasidagi hamma narsa
- 2.1 Birinchi o'ram
- 2.2 children ichida nima bo'ladi
- 2.3 {children} unutilsa
- 3. Props va children birga
- 3.1 Sarlavha — props, mazmun — children
- 3.2 Bir nechta "slot"
- 4. Wrapper komponentlar
- 5. Kompozitsiya va merosxo'rlik
- 5.1 Klasslarda meros bor edi
- 5.2 Nega kompozitsiya yutadi
- 6. children va oraliq komponentlar
- 7. children ga tur yozamiz
- 8. Vazifalar qadami: Qator va TahrirQatori
- 8.1 Qator — qatorning qobig'i
- 8.2 TahrirQatori — birinchi kompozitsiya
- 9. Ko'p uchraydigan xatolar
- 10. Mashqlar
- 1-mashq (oson): nima chiqadi?
- 2-mashq (o'rta): kartalar sahifasi
- 3-mashq (qiyin): chek (TypeScript)
- 4-mashq: Vazifalar qadami
- 11. Real ishda
- Xulosa
- Manbalar
children va kompozitsiya: React komponentlarini lego kabi yig'ish — slot, wrapper va Card naqshi
Qisqacha: Komponent teglari orasiga yozilgan hamma narsa — matn, element, boshqa komponent — unga
childrendegan prop bo'lib keladi:<Card>…</Card>→function Card({ children }). Komponent uni o'zi xohlagan joyga qo'yadi:<section>{children}</section>. Bir nechta "joy" kerak bo'lsa, JSX'ni oddiy props bilan ham berish mumkin:<Layout header={<Logo />} footer={…}>. React'da komponentlar bir-biridan meros olmaydi (extendsyo'q) — ular bir-birining ichiga qo'yiladi. Bu kompozitsiya deyiladi.
Bu darsda
childrenqanday paydo bo'lishini va unda nima bo'lishi mumkinligini bilasiz.- Ichiga istalgan narsa qo'yiladigan "o'ram" komponent (
Card,Section) yozasiz. - Bir nechta slot'li komponent yasaysiz:
header,footerprops orqali. - Nega React merosxo'rlik o'rniga kompozitsiyani tanlaganini tushuntira olasiz.
childrenga TypeScript turi (ReactNode) yozasiz.
Oldin bilishingiz kerak: Props: komponentga ma'lumot uzatish, JSX II: ifodalar, Fragment va nima ekranga chiqadi.
1. Nega bu kerak?
«Bahor» saytida bir xil ko'rinishdagi "kartochkalar" ko'p. Taom kartasi, aksiya kartasi, aloqa kartasi — hammasida ramka, soya va sarlavha bor. Ichidagisi esa butunlay har xil: birida narx va rasm, birida muddat, birida telefon va xarita.
Props darsida qiymatni atribut bilan berishni o'rgandik. Lekin kartaning ichidagi butun bir bo'lakni — bir nechta paragraf, tugma, ro'yxatni — content="…" atributiga sig'dirish noqulay. Bizga HTML'dagidek yozish kerak: ochuvchi teg, ichida mazmun, yopuvchi teg.
vazifalar da ham shu muammo bor. render.ts dagi oddiyQator() ham, tahrirQatori() ham bir xil boshlanadi: <li> yaratiladi, unga data-id yoziladi, keyin ichiga har xil narsa qo'shiladi. Qobiq bir xil, ichi har xil. Hayotiy o'xshatish: ovqat qutisi (lanchboks). Quti bitta, ichiga bugun osh, ertaga manti solasiz. Quti ichida nima borligini bilmaydi — u faqat o'raydi.
2. children — teglar orasidagi hamma narsa
2.1 Birinchi o'ram
function Card({ children }) {
return <section className="card">{children}</section>;
}
function App() {
return (
<div>
<Card>
<h2>Osh</h2>
<p>35000 so'm</p>
</Card>
<Card>
<h2>Aksiya</h2>
<p>Har juma — ko'k choy bepul</p>
</Card>
</div>
);
}Ekranda:
Osh
35000 so'm
Aksiya
Har juma — ko'k choy bepul<Card> va </Card> orasidagi ikki element Card ga children prop'i bo'lib keldi. Card esa ularni <section> ichiga qo'ydi. DOM'da natija: ikkita <section class="card">, har birining ichida <h2> va <p>.
JSX I darsidagi transpiler chiqishini eslang. <p>Osh</p> → jsx("p", { children: "Osh" }). Teglar orasidagi mazmun har doim children kalitiga tushadi — HTML teglarida ham, sizning komponentingizda ham. Farqi: <p> ning children ini React o'zi chizadi, Card niki esa — siz {children} deb qayerga yozsangiz, o'sha yerda.
2.2 children ichida nima bo'ladi
Turi — teglar orasida nima yozilganiga bog'liq:
function Show({ children }) {
console.log(typeof children, Array.isArray(children));
return <p>[{children}]</p>;
}
function App() {
return (
<div>
<Show>Osh</Show>
<Show>Osh {35000}</Show>
<Show>
<b>Osh</b>
</Show>
<Show />
</div>
);
}Konsolda:
string false
object true
object false
undefined falseEkranda:
[Osh]
[Osh 35000]
[Osh]
[]| Teglar orasida | children |
|---|---|
| faqat matn | satr: "Osh" |
bir nechta bo'lak (matn va {}) |
massiv: ["Osh ", 35000] |
| bitta element | bitta element obyekti |
hech narsa (<Show />) |
undefined |
Bu turlarning hammasini React JSX II dagi qoidalar bilan chizadi. Shuning uchun komponent ichida children ning turini tekshirish deyarli hech qachon kerak emas — uni {children} qilib qo'yish yetadi.
2.3 {children} unutilsa
Eng ko'p uchraydigan xato — jim:
function Card({ title }) {
return (
<section>
<h2>{title}</h2>
</section>
);
}
function App() {
return (
<Card title="Osh">
<p>35000 so'm</p>
</Card>
);
}Ekranda:
OshNarx yo'q, ogohlantirish ham yo'q. children keldi, lekin Card uni hech qayerga qo'ymadi. Komponent o'zi qaytargan narsani chizadi — boshqasini emas. JavaScript'da bu xato jim o'tadi. TypeScript'da esa jim o'tmaydi — buni «children ga tur yozamiz» bo'limida ko'ramiz.
Tekshirib ko'ring:
function Box({ children }) { return <div>{children}{children}</div>; }va<Box><b>Osh</b></Box>— ekranda nima chiqadi?
Javob
"OshOsh" — ikkita <b>. children — oddiy qiymat, uni xohlagancha marta ishlatish mumkin. React har o'rin uchun alohida DOM elementi yasaydi. Element obyekti esa bitta: u "buyurtma qog'ozi", DOM elementi emas (JSX I).
3. Props va children birga
3.1 Sarlavha — props, mazmun — children
Qoida oddiy: qisqa qiymat (matn, son) — props'da, katta JSX bo'lagi — children da:
function Card({ title, children }) {
return (
<section className="card">
<h2>{title}</h2>
{children}
</section>
);
}
function App() {
return (
<div>
<Card title="Osh">
<p>Choyxona oshi, 1 porsiya</p>
<p>35000 so'm</p>
</Card>
<Card title="Aloqa">
<p>Tel: +998 90 000 00 00</p>
</Card>
</div>
);
}Ekranda:
Osh
Choyxona oshi, 1 porsiya
35000 so'm
Aloqa
Tel: +998 90 000 00 00Card sarlavha qayerda turishini va ramkani biladi. Ichida nima borligini esa bilmaydi va bilishi shart emas. Ertaga kartaga rasm yoki tugma qo'shsangiz, Card ga tegmaysiz.
3.2 Bir nechta "slot"
children — bitta joy. Sahifa sxemasida esa joy ko'p: tepada sarlavha, o'rtada mazmun, pastda pastki qism. Har biriga JSX kerak. Yechim: JSX'ni oddiy props bilan berish. Element ham qiymat-ku (JSX II):
function PageLayout({ header, footer, children }) {
return (
<div className="sahifa">
<header>{header}</header>
<main>{children}</main>
<footer>{footer}</footer>
</div>
);
}
function App() {
return (
<PageLayout
header={<h1>«Bahor» oshxonasi</h1>}
footer={<small>07:00–23:00, har kuni</small>}
>
<p>Bugun: osh, manti, lag'mon</p>
</PageLayout>
);
}Ekranda:
«Bahor» oshxonasi
Bugun: osh, manti, lag'mon
07:00–23:00, har kuniBunday "teshik" — slot deyiladi: komponent joyni belgilaydi, nima qo'yilishini chaqiruvchi hal qiladi. children — asosiy slot, header va footer — nomli slot'lar. Web Components dagi <slot name="header"> ham aynan shu g'oya. React'da u oddiy props.
Diagrammada ko'ring: ma'lumot qaysi yo'l bilan qaysi teshikka tushadi.
flowchart LR
A["App"] -- "header=" --> H["header slot"]
A -- "teglar orasi" --> M["children slot"]
A -- "footer=" --> F["footer slot"]
subgraph PageLayout
H
M
F
endApp uchta bo'lakni beradi, PageLayout esa ularning joyini va o'ramini biladi. Sahifa sxemasi bir joyda — butun saytda bir xil.
Tekshirib ko'ring:
PageLayoutnifootersiz chaqirsak nima bo'ladi?
Javob
footer — undefined, {footer} hech narsa chizmaydi. Lekin bo'sh <footer></footer> elementi DOM'da qoladi. Uni ham olib tashlash kerak bo'lsa — shart bilan: {footer && <footer>{footer}</footer>}. Shartli chizish — keyingi dars.
4. Wrapper komponentlar
"O'ram" (wrapper) — o'zi hech narsa qo'shmaydigan, faqat ichidagisini bezaydigan yoki tartiblaydigan komponent. Ular kichik, lekin butun sayt bo'ylab qayta ishlatiladi:
function Highlight({ children }) {
return <mark className="ajratma">{children}</mark>;
}
function PriceRow({ children }) {
return <p className="narx-qatori">{children}</p>;
}
function App() {
return (
<section>
<PriceRow>
Osh: <Highlight>35000</Highlight> so'm
</PriceRow>
<PriceRow>
Manti: 30000 so'm <Highlight>Yangi!</Highlight>
</PriceRow>
</section>
);
}Ekranda:
Osh: 35000 so'm
Manti: 30000 so'm Yangi!Wrapper'ning foydasi: dizayner "ajratilgan narxlar endi sariq emas, yashil bo'lsin" desa, faqat Highlight o'zgaradi. U ishlatilgan 40 joyga tegilmaydi.
Ichma-ich ham bo'ladi: <Card><PriceRow><Highlight>…</Highlight></PriceRow></Card>. Har komponent faqat o'z qatlamini biladi — matryoshka kabi.
5. Kompozitsiya va merosxo'rlik
5.1 Klasslarda meros bor edi
Meros: extends va super darsida klass boshqa klassdan meros olardi. Shunday fikr kelishi tabiiy: "WarningCard extends Card" — ogohlantirish kartasi oddiy kartaning maxsus turi.
React komponentlari esa — funksiyalar, va ular meros olmaydi. Maxsus variant ichiga qo'yish bilan yasaladi:
function Card({ title, children }) {
return (
<section className="card">
<h2>{title}</h2>
{children}
</section>
);
}
function WarningCard({ children }) {
return (
<Card title="Diqqat!">
<div className="ogohlantirish">{children}</div>
</Card>
);
}
function App() {
return (
<WarningCard>
<p>Bugun 22:00 da yopilamiz.</p>
</WarningCard>
);
}Ekranda:
Diqqat!
Bugun 22:00 da yopilamiz.WarningCard — Card ning "maxsus turi". Lekin u Card dan meros olmadi: shunchaki uni o'z ichida ma'lum props bilan chizdi. Bu kompozitsiya (composition) — kichik bo'laklarni bir-birining ichiga qo'yib, kattasini yig'ish.
5.2 Nega kompozitsiya yutadi
Meros (extends) |
Kompozitsiya | |
|---|---|---|
| Aloqa | qattiq: bola otaning ichini biladi | yumshoq: faqat props orqali |
| O'zgartirish | ota o'zgarsa — hamma bolalar xavf ostida | har bo'lak alohida |
| Aralashtirish | bitta ota | istalgan bo'laklar birikmasi |
| Tekshirish | ierarxiyani bilish kerak | props'ga qarash yetadi |
React jamoasining eski rasmiy hujjatida shunday yozilgan: Facebook'da (hozirgi Meta) minglab komponent bor, lekin merosxo'rlik ierarxiyasi kerak bo'lgan birorta holat topilmagan. Bu Asosiy tamoyillar: kompozitsiya darsidagi "kompozitsiya — merosdan afzal" qoidasining React'dagi ko'rinishi.
Maslahat: Eski kodda
React.Children.map,cloneElementkabichildrenni o'zgartiruvchi API'larni uchratasiz. Ular hali bor, lekin hujjatda "kam ishlatiladigan" deb belgilangan. Yangi kodda props va slot'lar yetadi (HOC va render props darsida eski naqshlarni o'qiymiz).
6. children va oraliq komponentlar
Kompozitsiyaning yana bir foydasi bor. Oraliq komponent ma'lumotga tegmasdan uni o'tkazib yuboradi:
function Sidebar({ children }) {
return <aside className="yon-panel">{children}</aside>;
}
function UserBadge({ name }) {
return <p>Ofitsiant: {name}</p>;
}
function App() {
const waiter = "Sardor";
return (
<Sidebar>
<UserBadge name={waiter} />
</Sidebar>
);
}Ekranda:
Ofitsiant: SardorSidebar waiter haqida hech narsa bilmaydi — unga name prop'i ham kerak emas. UserBadge ni App o'zi yasadi va tayyor holda Sidebar ichiga qo'ydi. Agar Sidebar ichida UserBadge yozilganda edi, name ni App → Sidebar → UserBadge deb ikki pog'ona tashish kerak bo'lardi. Ko'p pog'onali tashish (props drilling) muammosini Context I darsida batafsil ko'ramiz — ko'pincha birinchi yechim aynan children.
7. children ga tur yozamiz
TypeScript'da children ning turi — ReactNode, JSX II dagi "{} ga qo'yish mumkin bo'lgan hamma narsa":
import type { ReactNode } from "react";
type CardProps = {
title: string;
children: ReactNode;
};
function Card({ title, children }: CardProps) {
return (
<section>
<h2>{title}</h2>
{children}
</section>
);
}
export default function App() {
return (
<Card title="Manti">
<p>30000 so'm</p>
</Card>
);
}Ekranda:
Manti
30000 so'mimport type — faqat tur import qilinadi, build'dan keyin bu qator yo'qoladi (Modullar TypeScript'da dagidek). Endi ikki xato kompilyatsiyada ushlanadi:
import type { ReactNode } from "react";
type CardProps = {
title: string;
children: ReactNode;
};
function Card({ title, children }: CardProps) {
return (
<section>
<h2>{title}</h2>
{children}
</section>
);
}
export function App() {
return (
<div>
<Card title="Osh" />
<Card title="Manti">{{ narx: 30000 }}</Card>
</div>
);
}Xato:
TS2741: Property 'children' is missing in type '{ title: string; }' but required in type 'CardProps'.
TS2353: Object literal may only specify known properties, and 'narx' does not exist in type 'Iterable<ReactNode> | Promise<AwaitedReactNode> | ReactElement<unknown, string | JSXElementConstructor<any>> | ReactPortal'.Birinchisi — "children majburiy, lekin berilmagan". Bo'sh karta ma'nosiz bo'lsa, children majburiy qolsin. Bo'sh bo'lishi mumkin bo'lsa — children?: ReactNode. Ikkinchisi — obyekt ReactNode emas (JSX II dagi Objects are not valid as a React child endi kompilyatsiyada). Xabardagi uzun ro'yxat — ReactNode ning ichidagi turlar, uni yod olish shart emas.
Teskari holat ham bor. children turida yo'q bo'lsa-yu, uni bersangiz:
type CardProps = { title: string };
function Card({ title }: CardProps) {
return <h2>{title}</h2>;
}
export function App() {
return (
<Card title="Osh">
<p>35000 so'm</p>
</Card>
);
}Xato:
TS2322: Type '{ title: string; children: Element; }' is not assignable to type 'IntrinsicAttributes & CardProps'.
Property 'children' does not exist on type 'IntrinsicAttributes & CardProps'."children xususiyati CardProps da yo'q." «{children} unutilsa» bo'limidagi jim xato — TypeScript'da jim emas. Komponent children ni qabul qilmasa, uni berish kompilyatsiya xatosi.
8. Vazifalar qadami: Qator va TahrirQatori
8.1 Qator — qatorning qobig'i
v6 da ikkala qator funksiyasi bir xil boshlanardi:
const li = document.createElement("li");
li.dataset.id = String(vazifa.id);
// faqat oddiy qatorda:
li.classList.toggle("bajarildi", vazifa.bajarildi);Bu — qobiq. Ichi esa har xil: oddiy qatorda katak, yorliq va ikki tugma; tahrirda maydon va boshqa ikki tugma. Qobiqni children li komponentga chiqaramiz — src/Qator.tsx:
// Qator.tsx — ro'yxat qatorining "qobig'i" (17/#07: children).
// Oddiy qator ham, tahrir qatori ham <li> ichida turadi; ichiga nima
// qo'yilishi — chaqiruvchining ishi (kompozitsiya)
import type { ReactNode } from "react";
type Props = {
id: number;
bajarildi?: boolean;
children: ReactNode;
};
export function Qator({ id, bajarildi = false, children }: Props) {
return (
// data-id — vanilla kod (fokus, qo'shni qator) shunga qaraydi
<li data-id={id} className={bajarildi ? "bajarildi" : undefined}>
{children}
</li>
);
}Uch narsaga e'tibor bering:
data-id={id}— son. v6 daString(vazifa.id)bilan aniq satrga aylantirardik, chunkidatasetfaqat satr qabul qiladi. JSX'da React atribut qiymatini o'zi satrga aylantiradi.className={bajarildi ? "bajarildi" : undefined}—classList.togglening o'rnida.undefinedbo'lsa,classatributi umuman yozilmaydi.bajarildiixtiyoriy va defaultfalse: tahrir qatori uni bermaydi.children: ReactNode— majburiy: bo'sh qator bo'lmaydi.
8.2 TahrirQatori — birinchi kompozitsiya
Endi tahrirQatori() ning o'rnini src/TahrirQatori.tsx egallaydi. U ikkita oldingi komponentni yig'adi — Qator (qobiq) va AmalTugmasi (Props darsida yozganimiz):
// TahrirQatori.tsx — tahrir paytidagi qator: maydon va ikki tugma
import { AmalTugmasi } from "./AmalTugmasi.tsx";
import { Qator } from "./Qator.tsx";
import { Vazifa } from "./vazifa.ts";
import type { VazifaMalumoti } from "./turlar.ts";
// tahrirMaydoni() (render.tsx) shu id bilan topadi
export const TAHRIR_MAYDONI_ID = "tahrir-maydon";
type Props = {
vazifa: VazifaMalumoti;
};
export function TahrirQatori({ vazifa }: Props) {
return (
<Qator id={vazifa.id}>
{/* defaultValue — boshlang'ich qiymat, keyin maydon o'ziniki
(uncontrolled). Fon yangilanganda React shu <input> ni
QAYTA YARATMAYDI — yozilayotgan matn joyida qoladi */}
<input
id={TAHRIR_MAYDONI_ID}
defaultValue={vazifa.matn}
maxLength={Vazifa.MAKS_UZUNLIK}
aria-label="Vazifa matni"
/>
<AmalTugmasi amal="saqla" matn="Saqlash" nomi={vazifa.matn} />
<AmalTugmasi
amal="bekor"
matn="Bekor qilish"
nomi={vazifa.matn}
/>
</Qator>
);
}Qatorma-qator:
<Qator id={vazifa.id}>…</Qator>— maydon va ikki tugmaQatorningchildreni bo'lib ketdi.bajarildiberilmagan — tahrir qatorida klass yo'q, v6 dagidek.vazifa: VazifaMalumoti— butun vazifa bitta prop bo'lib keladi.VazifaMalumoti—turlar.tsdagi JSON shakli (id,matn,bajarildi, hammasireadonly). Props faqat o'qiladi — tur ham shuni aytadi.defaultValue—valueemas.defaultValuemaydonga faqat birinchi qiymatni beradi, keyin maydon foydalanuvchiniki. Bu "uncontrolled" maydon — Formalar II darsida chuqur. Izohdagi gap muhim. Tahrir paytida boshqa tabdan o'zgarish kelsa, ro'yxat qayta chiziladi. Lekin React o'sha<input>ni qayta yaratmaydi — yozilayotgan matn joyida qoladi. v6 da buning uchun "qoralamani qo'lda tiklash" kodi bor edi.TAHRIR_MAYDONI_ID— maydonning id'si eksport qilinadi: vanilla kod (render.tsdagitahrirMaydoni()) maydonni shu bilan topadi va fokus beradi. Izohdarender.tsxdeyilgani — fayl Ro'yxatlar va key darsida shu nomga o'tadi (ichida JSX paydo bo'ladi). Komponent faylidan konstanta eksport qilish — Komponentlar darsidagionly-export-componentsholati. Buvazifalarda Fast Refresh uchun ozgina narx; Hodisalarni boshqarish darsida bu eksport keraksiz bo'ladi.maxLength={Vazifa.MAKS_UZUNLIK}— 100 belgi,vazifa.tsdagi o'sha qoida. HTML'dagimaxlengthJSX'da camelCase (JSX I).
npm run tip jim tugaydi. Ekranda hali hech narsa o'zgarmadi: komponentlar tayyor, lekin ularni hali hech kim chizmaydi. Keyingi darsda oddiy qatorni yozamiz. U yerda tahrir yoki oddiy ko'rinishni tanlaydigan VazifaQatori ham yig'iladi.
9. Ko'p uchraydigan xatolar
| Belgi | Sabab | Davosi |
|---|---|---|
| ichidagi mazmun ko'rinmaydi | {children} qaytarilgan JSX'da yo'q |
{children} ni joyiga qo'ying |
TS2322 … 'children' does not exist |
props turida children yo'q |
children: ReactNode qo'shing |
TS2741 … 'children' is missing |
majburiy children berilmagan |
mazmun bering yoki children?: |
Objects are not valid as a React child |
children ga obyekt berilgan |
maydonlarini chiqaring |
bo'sh <footer> qoladi |
slot berilmagan, o'ram qolgan | {footer && <footer>…} |
extends Card bilan "maxsus karta" |
klass merosi odati | ichiga qo'ying (kompozitsiya) |
10. Mashqlar
Mashqlar kurs/mashqlar/17/07-children/ da. Har yechimni «Ishga tushir» bilan sinang.
1-mashq (oson): nima chiqadi?
Ishga tushirmasdan oldin ekranni yozing.
function Box({ title, children }) {
return (
<div>
<h3>{title}</h3>
<p>[{children}]</p>
</div>
);
}
function Empty({ children }) {
return <p>Bo'sh quti</p>;
}
function App() {
return (
<div>
<Box title="A">Osh</Box>
<Box title="B" />
<Empty>Manti</Empty>
</div>
);
}Bsarlavhasi ostidagi qator: ]Emptyichidagi "Manti" ekranda bormi (ha/yo'q):
Yechim
Ekranda:
A
[Osh]
B
[]
Bo'sh qutiB — children yo'q (undefined), qavslar orasi bo'sh. Empty children ni oladi, lekin hech qayerga qo'ymaydi — "Manti" yo'qoladi va xato chiqmaydi.
2-mashq (o'rta): kartalar sahifasi
Card komponentini yozing: props — title, children va ixtiyoriy footer. footer berilsa, u <small> ichida kartaning pastida chiqsin. Berilmasa, <small> umuman bo'lmasin. Shart uchun {footer && …} yetadi: footer — satr, element yoki undefined, son emas, shuning uchun 0 tuzog'i yo'q. App uchta karta chizsin:
Osh
Choyxona oshi
35000 so'm
Manti
4 dona
30000 so'm
Aloqa
+998 90 000 00 00Birinchi ikkita kartada narx — footer, uchinchisida footer yo'q.
Yechim
function Card({ title, footer, children }) {
return (
<section className="card">
<h2>{title}</h2>
{children}
{footer && <small>{footer}</small>}
</section>
);
}
function App() {
return (
<div>
<Card title="Osh" footer="35000 so'm">
<p>Choyxona oshi</p>
</Card>
<Card title="Manti" footer={<b>30000 so'm</b>}>
<p>4 dona</p>
</Card>
<Card title="Aloqa">
<p>+998 90 000 00 00</p>
</Card>
</div>
);
}Ekranda:
Osh
Choyxona oshi
35000 so'm
Manti
4 dona
30000 so'm
Aloqa
+998 90 000 00 00Bu yerda <small> — inline element. U yangi qatorda chiqdi, chunki undan oldingi <p> — blok element. Slot'ga satr ham ("35000 so'm"), element ham (<b>…</b>) berish mumkin — ikkalasi ham ReactNode.
3-mashq (qiyin): chek (TypeScript)
«Bahor» kassasi uchun chek yasang, .tsx da. Ikki komponent:
Receipt— props:title: string,children: ReactNode,total: ReactNode(slot). Chizadi:<h2>da sarlavha, keyin<ul>ichidachildren, oxirida<p>daJami:vatotal.ReceiptLine— props:name: string,price: number,count?: number(default 1). Chizadi:<li>—Osh × 2: 70000.
App chek chizsin: osh × 2, ko'k choy × 3, non (3000). total slotiga jami summani <b> ichida bering — uni App hisoblasin (70000 + 15000 + 3000). Ekranda:
Chek №17
Osh × 2: 70000
Ko'k choy × 3: 15000
Non × 1: 3000
Jami: 88000 so'mIshora: «Bir nechta "slot"» va «children ga tur yozamiz» bo'limlari.
Yechim
import type { ReactNode } from "react";
type ReceiptProps = {
title: string;
children: ReactNode;
total: ReactNode;
};
function Receipt({ title, children, total }: ReceiptProps) {
return (
<section>
<h2>{title}</h2>
<ul>{children}</ul>
<p>Jami: {total}</p>
</section>
);
}
type ReceiptLineProps = {
name: string;
price: number;
count?: number;
};
function ReceiptLine({ name, price, count = 1 }: ReceiptLineProps) {
return (
<li>
{name} × {count}: {price * count}
</li>
);
}
export default function App() {
const total = 35000 * 2 + 5000 * 3 + 3000;
return (
<Receipt title="Chek №17" total={<b>{total} so'm</b>}>
<ReceiptLine name="Osh" price={35000} count={2} />
<ReceiptLine name="Ko'k choy" price={5000} count={3} />
<ReceiptLine name="Non" price={3000} />
</Receipt>
);
}Ekranda:
Chek №17
Osh × 2: 70000
Ko'k choy × 3: 15000
Non × 1: 3000
Jami: 88000 so'mReceipt qatorlar haqida hech narsa bilmaydi — u faqat chek shaklini beradi. ReceiptLine esa chek haqida bilmaydi — u bitta qator. Ularni App yig'di: bu kompozitsiya. Jami summa hozircha qo'lda hisoblangan. Ro'yxat massivdan chizilganda uni reduce bilan hisoblash mumkin bo'ladi (Ro'yxatlar va key).
4-mashq: Vazifalar qadami
refactor/royxat-react branch'ida src/Qator.tsx va src/TahrirQatori.tsx ni «Vazifalar qadami» bo'limidagidek yozing. npm run tip toza bo'lsin. Savol: TahrirQatori da nega <Qator> ga bajarildi berilmagan, OddiyQator da esa beriladi (keyingi darsda ko'rasiz)?
Yechim
v6 dagi tahrirQatori() ham bajarildi klassini qo'ymasdi — tahrir paytida qator chizilmagan (ustidan chiziq yo'q) ko'rinadi. Qator da bajarildi ixtiyoriy va default false, shuning uchun TahrirQatori uni yozmaydi. Oddiy qator esa vazifa holatiga qarab chiziladi va bajarildi={vazifa.bajarildi} beradi. Bitta qobiq — ikki xil ishlatish: slot'ga har xil mazmun, props'ga har xil qiymat.
11. Real ishda
- Layout komponentlari — har loyihada:
PageLayout,Sidebar,Modal,Card. Ularchildrenva nomli slot'lar bilan yoziladi. - UI kutubxonalari (shadcn/ui, Radix, MUI) — kompozitsiya ustiga qurilgan:
<Dialog><DialogTitle>…</DialogTitle></Dialog>. Bunday "bir-biriga bog'langan komponentlar" naqshi — Compound komponentlar va slot naqshi darsida. - Optimallashtirish:
childrenorqali berilgan JSX ota qayta chizilganda ham qayta yasalmaydi — bu bepul tezlashtirish usuli (Kompozitsiya orqali optimallashtirish). - Intervyu savollari: "
childrennima?", "React'da merosxo'rlik ishlatiladimi?", "Komponentga bir nechta JSX bo'lagini qanday berasiz?".
Xulosa
- Teglar orasidagi hamma narsa komponentga
childrenprop'i bo'lib keladi; uni{children}bilan kerakli joyga qo'yasiz. {children}unutilsa — mazmun jim yo'qoladi; TypeScript turidachildrenbo'lmasa, uni berish — xato.- Qisqa qiymat — props, katta JSX bo'lagi —
children; bir nechta joy — JSX'ni nomli props (slot) bilan bering. - Maxsus variant meros bilan emas, ichiga qo'yish bilan yasaladi — bu kompozitsiya.
childrenturi —ReactNode.vazifalardaQator— umumiy<li>qobig'i,TahrirQatori—QatorvaAmalTugmasidan yig'ilgan birinchi kompozitsiya.
Keyingi dars: Shartli render — if, ternary va && bilan qaysi UI chizilishini tanlaymiz va vazifalar da tahrir yoki oddiy qatorni tanlaydigan VazifaQatori ni yozamiz.
Manbalar
- React: "Passing Props to a Component" — "Passing JSX as children" — react.dev/learn/passing-props-to-a-component
- React:
ChildrenvacloneElement— "Legacy React APIs" — react.dev/reference/react/legacy - React (eski hujjat): "Composition vs Inheritance" — legacy.reactjs.org/docs/composition-vs-inheritance.html
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!