16-bo‘lim
Kompozitsiya naqshlari
children bilan o'rash, props sifatida JSX, birlashtirilgan komponentlar, chizish funksiyasi va props burg'ulashni kompozitsiya bilan hal qilish.
Ushbu bo‘lim mundarijasi
React da qayta ishlatishning asosiy usuli - kompozitsiya: komponentlarni bir-birining ichiga joylash.
Bu bo'limda amalda uchraydigan naqshlarni ko'ramiz.
Sozlash emas, kompozitsiya #
import { renderToStaticMarkup } from "react-dom/server";
import { chiroyli } from "./dom-muhit.mjs";
function SozlanadiganPanel({ sarlavha, matn, tugmaMatni, tugmaBormi }) {
return (
<section>
<h3>{sarlavha}</h3>
<p>{matn}</p>
{tugmaBormi && <button>{tugmaMatni}</button>}
</section>
);
}
function Panel({ sarlavha, children }) {
return (
<section>
<h3>{sarlavha}</h3>
{children}
</section>
);
}
console.log(chiroyli(renderToStaticMarkup(
<SozlanadiganPanel
sarlavha="Birinchi"
matn="Matn"
tugmaBormi
tugmaMatni="Bosish"
/>,
)));
console.log("---");
console.log(chiroyli(renderToStaticMarkup(
<Panel sarlavha="Ikkinchi">
<p>Matn</p>
<button>Bosish</button>
<small>Va istalgan boshqa narsa</small>
</Panel>,
)));
<section>
<h3>Birinchi</h3>
<p>Matn</p>
<button>Bosish</button>
</section>
---
<section>
<h3>Ikkinchi</h3>
<p>Matn</p>
<button>Bosish</button>
<small>Va istalgan boshqa narsa</small>
</section>
Natija bir xil, lekin ikkinchi yondashuv cheksiz moslashuvchan.
SozlanadiganPanel ni kengaytirish uchun har safar yangi
prop kerak: ikonka, ikkinchi tugma, pastki matn, rang.
Bir yildan keyin unda yigirmata prop bo'ladi va ularning yarmi faqat bitta joyda ishlatiladi.
Panel esa hech qachon o'zgarmaydi: ichiga nima qo'ysangiz,
o'sha chiziladi.
Oddiy belgi: prop nomida Bormi, Korinsinmi, Turi kabi
so'zlar ko'paysa - bu kompozitsiyaga o'tish vaqti kelganini
bildiradi.
Bir nechta joy #
import { renderToStaticMarkup } from "react-dom/server";
import { chiroyli } from "./dom-muhit.mjs";
function Kartochka({ boshi, tanasi, oyogi }) {
return (
<article>
<header>{boshi}</header>
<div className="tana">{tanasi}</div>
{oyogi && <footer>{oyogi}</footer>}
</article>
);
}
console.log(chiroyli(renderToStaticMarkup(
<Kartochka
boshi={<h3>Malika</h3>}
tanasi={<p>88 ball</p>}
oyogi={<button>Batafsil</button>}
/>,
)));
console.log("---");
console.log(chiroyli(renderToStaticMarkup(
<Kartochka boshi={<h3>Aziza</h3>} tanasi={<p>79 ball</p>} />,
)));
<article>
<header>
<h3>Malika</h3>
</header>
<div class="tana">
<p>88 ball</p>
</div>
<footer>
<button>Batafsil</button>
</footer>
</article>
---
<article>
<header>
<h3>Aziza</h3>
</header>
<div class="tana">
<p>79 ball</p>
</div>
</article>
children bitta joy beradi. Bir nechta joy kerak bo'lsa, JSX ni
oddiy props sifatida uzatish mumkin.
Ikkinchi misolda oyogi berilmadi - undefined bo'lgani uchun
footer umuman chizilmadi.
Birlashtirilgan komponentlar #
import { createContext, useContext, useState } from "react";
const YonalishKonteksti = createContext(null);
export function Yonalish({ children, boshlangich }) {
const [faol, tanla] = useState(boshlangich);
return (
<YonalishKonteksti value={{ faol, tanla }}>
<div className="yonalish">{children}</div>
</YonalishKonteksti>
);
}
export function Tugma({ nom, children }) {
const { faol, tanla } = useContext(YonalishKonteksti);
return (
<button
id={`t-${nom}`}
className={faol === nom ? "faol" : ""}
onClick={() => tanla(nom)}
>
{children}
</button>
);
}
export function Panel({ nom, children }) {
const { faol } = useContext(YonalishKonteksti);
if (faol !== nom) return null;
return <div id={`p-${nom}`}>{children}</div>;
}
import { Yonalish, Tugma, Panel } from "./yonalish.mjs";
import { chiz, bos, html } from "./dom-muhit.mjs";
await chiz(
<Yonalish boshlangich="profil">
<Tugma nom="profil">Profil</Tugma>
<Tugma nom="sozlama">Sozlamalar</Tugma>
<Panel nom="profil">Profil mazmuni</Panel>
<Panel nom="sozlama">Sozlama mazmuni</Panel>
</Yonalish>,
);
const korinadigan = () =>
document.querySelector("#p-profil") ? "profil" : "sozlama";
console.log("boshida:", korinadigan());
console.log("faol tugma:", document.querySelector(".faol").textContent);
await bos("#t-sozlama");
console.log("bosilgandan keyin:", korinadigan());
console.log("faol tugma:", document.querySelector(".faol").textContent);
boshida: profil
faol tugma: Profil
bosilgandan keyin: sozlama
faol tugma: Sozlamalar
Yonalish, Tugma va Panel birga ishlaydi, lekin
foydalanuvchi ularni istalgan tartibda joylashtira oladi.
Ular bir-biri bilan kontekst orqali gaplashadi - props uzatish kerak emas.
<Select> va <Option>, <Accordion> va <AccordionItem>,
<Menu> va <MenuItem> - hammasi shu naqshda yozilgan.
Foydasi: moslashuvchanlik. Foydalanuvchi tugmalar orasiga ajratgich qo'yishi, ularni o'rashi yoki tartibini o'zgartirishi mumkin - komponentni o'zgartirmasdan.
Muqobil yondashuv - massiv berish:
<Yonalish bolimlar={[{ nom: "profil", mazmun: "..." }]} />
U soddaroq, lekin har bir yangi ehtiyoj uchun massiv shaklini kengaytirish kerak bo'ladi.
Props burg'ulashni kompozitsiya bilan yechish #
import { renderToStaticMarkup } from "react-dom/server";
import { chiroyli } from "./dom-muhit.mjs";
function Tugma({ mavzu }) {
return <button className={mavzu}>Bosish</button>;
}
function YomonPanel({ mavzu }) {
return <div><Tugma mavzu={mavzu} /></div>;
}
function YaxshiPanel({ children }) {
return <div>{children}</div>;
}
const mavzu = "qorongi";
console.log(chiroyli(renderToStaticMarkup(<YomonPanel mavzu={mavzu} />)));
console.log("---");
console.log(chiroyli(renderToStaticMarkup(
<YaxshiPanel>
<Tugma mavzu={mavzu} />
</YaxshiPanel>,
)));
<div>
<button class="qorongi">Bosish</button>
</div>
---
<div>
<button class="qorongi">Bosish</button>
</div>
Natija bir xil, lekin YaxshiPanel mavzu haqida hech narsa
bilmaydi.
13-bo'limda props burg'ulash muammosini kontekst bilan yechgan edik. Lekin ko'pincha soddaroq yechim bor.
Element children sifatida uzatilsa, u yuqorida yaratiladi
va kerakli props ni o'sha yerda oladi. Oradagi komponentlar
uzatishda ishtirok etmaydi.
Bu kontekstdan afzalroq, chunki:
- Ma'lumot oqimi ochiq ko'rinadi;
- Qo'shimcha tuzilma kerak emas;
- Komponent mustaqil qoladi va sinash oson.
Kontekstni faqat kompozitsiya yordam bermaganda oling - masalan, ma'lumot juda chuqurda va ko'p joyda kerak bo'lganda.
Chizish funksiyasi #
import { renderToStaticMarkup } from "react-dom/server";
import { chiroyli } from "./dom-muhit.mjs";
function Royxat({ elementlar, chiz }) {
return (
<ul>
{elementlar.map((element, i) => (
<li key={element.id}>{chiz(element, i)}</li>
))}
</ul>
);
}
const talabalar = [
{ id: 1, ism: "Malika", ball: 88 },
{ id: 2, ism: "Husanboy", ball: 92 },
];
console.log(chiroyli(renderToStaticMarkup(
<Royxat elementlar={talabalar} chiz={(t) => <b>{t.ism}</b>} />,
)));
console.log("---");
console.log(chiroyli(renderToStaticMarkup(
<Royxat
elementlar={talabalar}
chiz={(t, i) => <span>{i + 1}. {t.ism} - {t.ball}</span>}
/>,
)));
<ul>
<li>
<b>Malika</b>
</li>
<li>
<b>Husanboy</b>
</li>
</ul>
---
<ul>
<li>
<span>1. Malika - 88</span>
</li>
<li>
<span>2. Husanboy - 92</span>
</li>
</ul>
Royxat qanday chizishni bilmaydi - buni chaqiruvchi
hal qiladi.
Bu naqsh ro'yxat mantig'ini (kalitlar, bo'sh holat, sahifalash) bir marta yozib, ko'rinishni har joyda boshqacha qilish imkonini beradi.
U kuchli, lekin kodni o'qishni qiyinlashtiradi: JSX ichida funksiya, uning ichida yana JSX.
Ko'pincha oddiyroq yechim bor - children bilan komponentni
uzatish:
<Royxat elementlar={talabalar}>
{(t) => <b>{t.ism}</b>}
</Royxat>
Yoki umuman ajratmasdan, har bir ro'yxat uchun alohida kichik komponent yozish.
Chizish funksiyasini faqat mantiq murakkab va ko'rinish har joyda boshqacha bo'lganda ishlating.
Komponentni prop sifatida #
import { renderToStaticMarkup } from "react-dom/server";
function Xabar({ Ikonka, matn }) {
return (
<div className="xabar">
<Ikonka />
<span>{matn}</span>
</div>
);
}
function Ogohlantirish() {
return <b>!</b>;
}
function Muvaffaqiyat() {
return <b>+</b>;
}
console.log(renderToStaticMarkup(
<Xabar Ikonka={Ogohlantirish} matn="Diqqat" />));
console.log(renderToStaticMarkup(
<Xabar Ikonka={Muvaffaqiyat} matn="Saqlandi" />));
<div class="xabar"><b>!</b><span>Diqqat</span></div>
<div class="xabar"><b>+</b><span>Saqlandi</span></div>
Komponentning o'zini prop sifatida uzatish mumkin.
Diqqat: prop nomi katta harf bilan - aks holda JSX uni HTML tegi deb biladi (4-bo'lim).
Naqshlarni tanlash #
| Ehtiyoj | Naqsh |
|---|---|
| Ichiga istalgan narsa qo'yish | children |
| Bir nechta alohida joy | JSX props |
| Birga ishlaydigan komponentlar to'plami | Kontekst + kompozitsiya |
| Ko'rinishni tashqaridan boshqarish | Chizish funksiyasi |
| Ikonka yoki shakl almashtirish | Komponent prop |
- Ko'p propsli komponentni
childrenga o'tkazing. - Ikki alohida joyli kartochka yozing.
- Berilmagan joy chizilmasligini tekshiring.
- Birlashtirilgan yo'nalish komponentini yozing.
- Uning qismlarini tartibini o'zgartirib joylang.
- Props burg'ulashni kompozitsiya bilan yeching.
- Uni kontekst bilan ham yechib, ikkalasini solishtiring.
- Chizish funksiyasi bilan ro'yxat yozing.
- Bir xil ro'yxatni ikki xil ko'rinishda chizing.
- Ikonkani komponent prop sifatida uzating.
Xulosa #
- Props soni o'sib borsa - kompozitsiyaga o'ting.
childrenbitta joy, JSX props bir nechta joy beradi.- Birga ishlaydigan komponentlar kontekst orqali gaplashadi va istalgan tartibda joylashadi.
- Props burg'ulashni ko'pincha kompozitsiya hal qiladi - kontekstdan oldin shuni sinang.
- Chizish funksiyasi kuchli, lekin o'qishni qiyinlashtiradi.
- Komponentni prop sifatida uzatganda nom katta harfli bo'lsin.
Keyingi bo'limda unumdorlikni o'rganamiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.