Mundarija (28)
- Bu darsda
- 1. Nega bu kerak?
- 2. if va erta return
- 2.1 Butunlay boshqa ko'rinish
- 2.2 null — "hech narsa chizma"
- 3. JSX ichida: ternary va &&
- 3.1 Ternary — ikkidan biri
- 3.2 && — bor yoki yo'q
- 3.3 0 && — qisqa takror
- 3.4 Ternary yoki &&?
- 4. JSX'ni o'zgaruvchiga saqlash
- 5. To'rt holat: yuklanmoqda, xato, bo'sh, tayyor
- 5.1 Jonli misol
- 5.2 TypeScript bilan: birorta holat unutilmasin
- 6. Shartli atributlar
- 7. Vazifalar qadami: BelgilanganMatn, OddiyQator, VazifaQatori
- 7.1 BelgilanganMatn — mos bo'laklar <mark> ichida
- 7.2 OddiyQator — katak, yorliq, ikki tugma
- 7.3 VazifaQatori — qaysi ko'rinish?
- 8. Ko'p uchraydigan xatolar
- 9. Mashqlar
- 1-mashq (oson): qaysi qator chiqadi?
- 2-mashq (o'rta): stol band qilish holati
- 3-mashq (qiyin): to'lov holati (TypeScript)
- 4-mashq: Vazifalar qadami
- 10. Real ishda
- Xulosa
- Manbalar
Shartli render: React'da if, ternary, && va null — yuklanish, xato va bo'sh holatlar
Qisqacha: React'da "qaysi UI chizilsin" degan savolga oddiy JavaScript javob beradi. Komponent boshida
if+return— butunlay boshqa ko'rinish uchun. JSX ichida ternary (a ? <X/> : <Y/>) — ikki variantdan biri uchun.&&— "bor yoki yo'q" uchun, lekin chap tomoni haqiqiy boolean bo'lsin (count > 0 &&, aks holda0ko'rinadi).nullqaytarish — "hech narsa chizma". Haqiqiy ilovada bitta ma'lumot to'rt holatda bo'ladi: yuklanmoqda, xato, bo'sh va tayyor — har biri o'z ekrani bilan.
Bu darsda
ifva ertareturnbilan komponentning butun ko'rinishini tanlaysiz.- JSX ichida ternary va
&&ni to'g'ri ishlatasiz,0 &&tuzog'idan qochasiz. - Komponentni
nullbilan yashirasiz va bu qaror kimniki ekanini tushunasiz. - Murakkab shartni JSX'dan oldin o'zgaruvchiga chiqarasiz.
- Yuklanish, xato, bo'sh va tayyor holatlarini to'liq chizasiz — TypeScript'da birorta ham unutilmaydigan qilib.
Oldin bilishingiz kerak: JSX II: ifodalar, Fragment va nima ekranga chiqadi, children va kompozitsiya, return va erta qaytish.
1. Nega bu kerak?
«Bahor» saytidagi buyurtma sahifasi. Mijoz "Buyurtmalarim" ni ochdi. Ma'lumot serverdan keladi — bir soniya kutish bor. Internet uzilib qolishi mumkin. Mijoz hali hech narsa buyurtma qilmagan bo'lishi ham mumkin. Va nihoyat, ro'yxat keldi.
Bitta joy — to'rt xil ekran: "Yuklanmoqda…", "Xato: internetni tekshiring", "Hali buyurtma yo'q" va ro'yxatning o'zi. Birini unutsangiz, mijoz bo'sh oq sahifaga qarab qoladi va "sayt buzilgan" deb o'ylaydi.
Vanilla'da bu if lar bilan yechilardi: vazifalar dagi qatorYasa() vazifa tahrirdami yoki yo'qmi, shunga qarab ikki funksiyadan birini chaqirardi. React'da ham xuddi shu if. JSX — JavaScript, shuning uchun alohida "shart sintaksisi" o'rganish shart emas. Faqat bitta cheklov bor: JSX I darsida ko'rganimizdek, {} ichida if yozib bo'lmaydi. Bugun shu cheklov atrofidagi to'rt usulni o'rganamiz.
2. if va erta return
2.1 Butunlay boshqa ko'rinish
Shartga qarab komponent butunlay boshqa JSX qaytarsa — oddiy if:
function WorkStatus({ hour }) {
if (hour < 7 || hour >= 23) {
return <p>Yopiq. Ertalab 07:00 da ochilamiz.</p>;
}
return (
<div>
<p>Ochiq!</p>
<p>Yopilishga {23 - hour} soat qoldi.</p>
</div>
);
}
function App() {
return (
<>
<WorkStatus hour={6} />
<WorkStatus hour={20} />
</>
);
}Ekranda:
Yopiq. Ertalab 07:00 da ochilamiz.
Ochiq!
Yopilishga 3 soat qoldi.if JSX'dan tashqarida — komponent funksiyasining oddiy qismida. Bu yerda JavaScript'ning hamma imkoniyati bor: if, else, switch, sikl. Erta return (erta qaytish) — "maxsus holatni birinchi hal qil, asosiy ko'rinish pastda qolsin". Funksiya qisqa va o'qilishi oson bo'ladi.
2.2 null — "hech narsa chizma"
Komponent o'zini butunlay yashirishi mumkin:
function SaleBanner({ isActive }) {
if (!isActive) {
return null;
}
return <p>Aksiya: har juma ko'k choy bepul!</p>;
}
function App() {
return (
<>
<h1>«Bahor»</h1>
<SaleBanner isActive={false} />
<p>Menyu pastda</p>
</>
);
}Ekranda:
«Bahor»
Menyu pastdanull — DOM'ga hech narsa qo'shmaydi. Lekin komponent baribir chaqirildi: React SaleBanner ni ishga tushirdi, u esa "hech narsa" deb javob berdi.
Savol: yashirish qarori kimniki — bolaniki yoki otaniki? Ikki yo'l bor:
| Bola o'zi yashiradi | Ota umuman chizmaydi | |
|---|---|---|
| Kod | if (!isActive) return null; |
{isActive && <SaleBanner />} |
| Qachon | qaror bolaning ma'lumotiga bog'liq | qaror otaning ma'lumotiga bog'liq |
| Komponent chaqiriladimi | ha | yo'q |
Odatda ikkinchisi tushunarliroq: otaning JSX'iga qarab, nima chizilishi darhol ko'rinadi.
Tekshirib ko'ring:
if (!isActive) return;(qiymatsizreturn) yozsak nima bo'ladi?
Javob
Ekran bir xil. Qiymatsiz return — undefined, React 19 esa uni null kabi "hech narsa" deb qabul qiladi (Komponentlar darsida return unutilgan holatda ko'rgandik). Lekin return null; aniqroq: "bu yerda ataylab hech narsa yo'q" deydi. TypeScript va linterlar ham shu shaklni kutadi.
3. JSX ichida: ternary va &&
3.1 Ternary — ikkidan biri
Ko'rinishning kichik bir qismi shartga bog'liq bo'lsa, butun komponentni ikki marta yozish ortiqcha. Ternary (if / else va shartli operator) — ifoda, demak {} ichiga sig'adi:
function MenuCard({ name, price, soldOut }) {
return (
<li className={soldOut ? "tugagan" : undefined}>
{name} — {soldOut ? <s>{price} so'm</s> : <b>{price} so'm</b>}
{soldOut ? " (tugadi)" : ""}
</li>
);
}
function App() {
return (
<ul>
<MenuCard name="Osh" price={35000} soldOut={false} />
<MenuCard name="Somsa" price={8000} soldOut />
</ul>
);
}Ekranda:
Osh — 35000 so'm
Somsa — 8000 so'm (tugadi)Ternary uch joyda ishladi: atributda (className), element tanlashda (<s> yoki <b>) va matnda. Atributdagi undefined — "atributni umuman qo'yma" (Props mashqida ko'rgandik).
3.2 && — bor yoki yo'q
"Else" qismi kerak bo'lmasa — &&. Mantiqiy operatorlar dan eslang: a && b — a rost bo'lsa b ni qaytaradi, aks holda a ning o'zini:
function CartBadge({ count, isVip }) {
return (
<p>
Savat
{isVip && " ⭐"}
{count > 0 && <b> ({count})</b>}
</p>
);
}
function App() {
return (
<>
<CartBadge count={3} isVip />
<CartBadge count={0} isVip={false} />
</>
);
}Ekranda:
Savat ⭐ (3)
Savat3.3 0 && — qisqa takror
Ikkinchi qatorda count > 0 yozilganiga e'tibor bering. JSX II darsida batafsil ko'rgan tuzog'imiz: {count && <b>…</b>} bo'sh savatda 0 ni chizadi. 0 && … → 0, son esa React'da ko'rinadi (false dan farqli). Qoida qisqa:
&&chapida son bo'lsa —count > 0 &&(yoki ternary);&&chapida boolean bo'lsa (isVip) — xavf yo'q;.length &&— o'sha son:items.length > 0 &&.
Batafsil misollar, NaN holati va TypeScript nega ushlamasligi — JSX II darsida.
3.4 Ternary yoki &&?
| Vaziyat | Usul | Misol |
|---|---|---|
| ikki variant | ternary | {isOpen ? "Ochiq" : "Yopiq"} |
| bor yoki yo'q | && (chapi boolean) |
{isVip && <Star />} |
| son bo'yicha bor/yo'q | taqqoslash + && |
{count > 0 && <Badge />} |
| atribut bor yoki yo'q | ternary + undefined |
className={x ? "a" : undefined} |
| butunlay boshqa ko'rinish | if + return |
«if va erta return» bo'limi |
Tekshirib ko'ring:
{name && <p>Salom, {name}!</p>}—namebo'sh satr""bo'lsa, ekranda nima chiqadi?0 &&dagidek tuzoq bormi?
Javob
Hech narsa chiqmaydi va tuzoq yo'q. "" && … → "", bo'sh satr esa ekranda hech narsa chizmaydi (JSX II jadvali). Tuzoq faqat sonlarda (0, NaN): ular ko'rinadi. Shunga qaramay, name !== "" && yozish niyatni aniqroq ko'rsatadi.
4. JSX'ni o'zgaruvchiga saqlash
Shart murakkablashsa, JSX ichidagi ternary'lar bir-birining ichiga kirib ketadi. "Ternary ichida ternary" — o'qib bo'lmaydigan kod. Yechim: JSX ham qiymat (JSX II), demak uni oldindan o'zgaruvchiga hisoblab qo'yish mumkin:
function DeliveryInfo({ distanceKm }) {
let message;
if (distanceKm <= 3) {
message = <b>Bepul yetkazamiz</b>;
} else if (distanceKm <= 10) {
message = <span>Yetkazish: {distanceKm * 2000} so'm</span>;
} else {
message = <span>Bu manzilga yetkazmaymiz</span>;
}
return <p>{distanceKm} km: {message}</p>;
}
function App() {
return (
<>
<DeliveryInfo distanceKm={2} />
<DeliveryInfo distanceKm={5} />
<DeliveryInfo distanceKm={15} />
</>
);
}Ekranda:
2 km: Bepul yetkazamiz
5 km: Yetkazish: 10000 so'm
15 km: Bu manzilga yetkazmaymizUch shoxli shart return dan oldin, oddiy if/else da. return esa faqat sxema: "masofa va xabar". Ichma-ich ternary bilan yozilganini o'qish ancha qiyin bo'lardi:
// ❌ o'qish qiyin
<p>{distanceKm} km: {distanceKm <= 3 ? <b>…</b> : distanceKm <= 10
? <span>…</span> : <span>…</span>}</p>5. To'rt holat: yuklanmoqda, xato, bo'sh, tayyor
5.1 Jonli misol
Endi «Nega bu kerak?» bo'limidagi "Buyurtmalarim" sahifasi. Ma'lumot serverdan kelishini hozircha tugmalar bilan taqlid qilamiz. Haqiqiy so'rov — useEffect va Effektda ma'lumot olish darslarida. Har tugma status va orders ni o'zgartirib, draw() ni chaqiradi (vanilla usul, JSX II dagidek). Blok tugmalarni ketma-ket o'zi bosadi:
import { createRoot } from "react-dom/client";
const root = createRoot(document.getElementById("root"));
let status = "loading";
let orders = [];
function OrderList({ status, orders }) {
if (status === "loading") {
return <p>Yuklanmoqda…</p>;
}
if (status === "error") {
return <p role="alert">Xato: internet aloqasini tekshiring.</p>;
}
if (orders.length === 0) {
return <p>Hali buyurtma yo'q. Menyuga o'ting!</p>;
}
return (
<ul>
{orders.map((o) => (
<li key={o.id}>{o.dish} × {o.count}</li>
))}
</ul>
);
}
function set(newStatus, newOrders) {
status = newStatus;
orders = newOrders;
draw();
}
function draw() {
console.log("holat:", status, orders.length);
root.render(
<div>
<OrderList status={status} orders={orders} />
<button onClick={() => set("error", [])}>Xato</button>
<button onClick={() => set("ready", [])}>Bo'sh</button>
<button onClick={() => set("ready", [
{ id: 1, dish: "Osh", count: 2 },
{ id: 2, dish: "Ko'k choy", count: 1 },
])}>Keldi</button>
</div>
);
}
draw();Konsolda:
holat: loading 0
holat: error 0
holat: ready 0
holat: ready 2Ekranda:
Osh × 2
Ko'k choy × 1
XatoBo'shKeldi«Ishga tushir» ni bosib, tugmalarni o'zingiz sinang. Har bosishda nima bo'lishi:
| Qadam | State | Ekranda |
|---|---|---|
| boshida | status: "loading" |
Yuklanmoqda… |
| «Xato» | status: "error" |
Xato: internet aloqasini tekshiring. |
| «Bo'sh» | status: "ready", orders: [] |
Hali buyurtma yo'q. Menyuga o'ting! |
| «Keldi» | status: "ready", 2 ta buyurtma |
Osh × 2 · Ko'k choy × 1 |
Erta return lar zanjiri — qaror daraxti. Diagrammada yuqoridan pastga o'qing: har savolda bitta shox tanlanadi.
flowchart TD
S{"status?"} -- "loading" --> L["Yuklanmoqda…"]
S -- "error" --> E["Xato xabari"]
S -- "ready" --> B{"orders bo'shmi?"}
B -- "ha" --> Y["Hali buyurtma yo'q"]
B -- "yo'q" --> R["Buyurtmalar ro'yxati"]Tartib muhim. Avval loading va error tekshiriladi: ular paytida orders hali haqiqiy emas. Keyin — bo'sh holat, eng oxirida — asosiy ko'rinish. Bu tartib erta return lar bilan o'z-o'zidan saqlanadi. Xato paragrafidagi role="alert" — Malika'ning ekran o'quvchisi xabarni darhol o'qib beradi (Dinamik UI'da qulaylik).
5.2 TypeScript bilan: birorta holat unutilmasin
Satrli status da xato oson: "loadng" deb yozsangiz — jim. Bunday holatlar uchun discriminated union bor. Har holat — o'z maydonlari bilan:
type Order = { id: number; dish: string; count: number };
type OrdersState =
| { kind: "loading" }
| { kind: "error"; message: string }
| { kind: "ready"; orders: Order[] };
function OrderList({ state }: { state: OrdersState }) {
switch (state.kind) {
case "loading":
return <p>Yuklanmoqda…</p>;
case "error":
return <p role="alert">Xato: {state.message}</p>;
case "ready":
if (state.orders.length === 0) {
return <p>Hali buyurtma yo'q.</p>;
}
return (
<ul>
{state.orders.map((o) => (
<li key={o.id}>{o.dish} × {o.count}</li>
))}
</ul>
);
default: {
const unhandled: never = state;
return unhandled;
}
}
}
export default function App() {
return (
<>
<OrderList
state={{ kind: "error", message: "server javob bermadi" }}
/>
<OrderList state={{ kind: "ready", orders: [] }} />
</>
);
}Ekranda:
Xato: server javob bermadi
Hali buyurtma yo'q.Ikki foyda bor. Birinchisi: state.message faqat "error" holatida bor — "loading" da uni o'qishga urinsangiz, tsc to'xtatadi. Ikkinchisi: default dagi never (to'liqlik tekshiruvi). Ertaga kimdir { kind: "empty" } qo'shib, switch ga yozishni unutsa — kompilyator xato beradi. vazifalar da shu naqsh bor: QoshishNatijasi turi va uning switch i (State I darsida ko'ramiz).
6. Shartli atributlar
Shart faqat elementni emas, atributni ham boshqaradi. Uch holat bilan tanishamiz:
function SubmitButton({ isSaving, hasError }) {
return (
<button
type="submit"
disabled={isSaving}
aria-invalid={hasError ? true : undefined}
>
{isSaving ? "Saqlanmoqda…" : "Saqlash"}
</button>
);
}
function App() {
return (
<form>
<SubmitButton isSaving={false} hasError={false} />
<SubmitButton isSaving hasError />
</form>
);
}Ekranda:
SaqlashSaqlanmoqda…disabled={isSaving}— boolean atribut:falsebo'lsa React uni umuman qo'ymaydi,truebo'lsa —disabled="".aria-invalid={hasError ? true : undefined}—aria-*atributlari esa satr sifatida yoziladi:falsebersangiz, DOM'daaria-invalid="false"qoladi. Shuning uchun "yo'q" holatda —undefined.- Matn — ternary bilan.
checked — alohida holat. Faqat o'qish uchun chizilgan katak:
function App() {
return (
<label>
<input type="checkbox" checked />
Osh tayyor
</label>
);
}Konsolda:
You provided a `checked` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultChecked`. Otherwise, set either `onChange` or `readOnly`.Ekranda:
Osh tayyor"Siz forma maydoniga checked berdingiz, lekin onChange ishlovchisi yo'q. U faqat o'qiladigan maydon bo'lib chiziladi. O'zgarishi kerak bo'lsa — defaultChecked ishlating. Aks holda onChange yoki readOnly qo'ying." React ogohlantirdi: "katak qiymatini sen boshqaryapsan, lekin bosilganda nima bo'lishini aytmading". Hozircha to'g'ri javob — readOnly: "bu katakni ataylab faqat ko'rsataman". Bu vazifalar dagi katakka kerak bo'ladi — «Vazifalar qadami» bo'limida.
7. Vazifalar qadami: BelgilanganMatn, OddiyQator, VazifaQatori
Bugun uchta komponent yoziladi va ro'yxat qatori to'liq bo'ladi. Kanon fayllaridagi uzun izoh qatorlari telefon ekraniga sig'ishi uchun qayta bo'lingan — mazmuni o'sha.
7.1 BelgilanganMatn — mos bo'laklar <mark> ichida
Qidiruv maydoniga "non" yozilsa, "Non olish" dagi mos bo'lak <mark> bilan ajratiladi. v6 dagi belgilanganMatn() <mark> elementlarini createElement bilan yasardi. Endi src/BelgilanganMatn.tsx:
// BelgilanganMatn.tsx — qidiruvga mos bo'laklar <mark> ichida
// (14/#11). v6 da: document.createElement("mark") + textContent.
// JSX'da {matn} — har doim matn: React uni o'zi ekranlaydi,
// "<b>" HTML bo'lib qolmaydi
import { moslar } from "./qidiruv.ts";
type Props = {
matn: string;
sorov: string;
};
export function BelgilanganMatn({ matn, sorov }: Props) {
const qismlar = [];
let joy = 0;
for (const [boshi, oxiri] of moslar(matn, sorov)) {
qismlar.push(matn.slice(joy, boshi));
// key: massivdagi element — React ularni tartib bo'yicha
// tanisin. Bo'lak boshi — shu matn ichida takrorlanmaydi
qismlar.push(<mark key={boshi}>{matn.slice(boshi, oxiri)}</mark>);
joy = oxiri;
}
qismlar.push(matn.slice(joy));
// Bo'sh satrlar ekranda ko'rinmaydi — v6 dagidek filtr shart emas
return <>{qismlar}</>;
}Bu yerdagi "shart" — for sikli ichida: mos bo'lak bo'lsa — <mark>, bo'lmasa — oddiy matn. moslar() (Matn algoritmlari darsida yozilgan qidiruv.ts dan) har mos bo'lakning [boshi, oxiri] oralig'ini beradi. Sorov bo'sh bo'lsa — bo'sh massiv, sikl bir marta ham aylanmaydi va butun matn bitta satr bo'lib qoladi.
Uch detal:
key={boshi}— massivdagi elementkeyso'raydi (JSX II). Bo'lak boshi bitta matn ichida takrorlanmaydi — yaxshi kalit.keyning to'liq qoidalari — keyingi darsda.- Bo'sh satrlar (
matn.slice(0, 0)→"") massivda qoladi, lekin ekranda hech narsa chizmaydi. v6 dagi.filter((qism) => qism !== "")endi kerak emas. qismlar.push— komponent ichida massivni o'zgartirish. Bu ruxsat etilganmi? Ha: massiv shu chaqiruvda yaratilgan. Nega bu muhim — Pure komponentlar darsida.
Komponentni jonli sinab ko'ramiz. moslar() o'rniga sodda nusxa — katta-kichik harfni farqlamaydigan indexOf:
// Sodda moslar(): katta-kichik harf farqsiz, apostrof qoidalarisiz
function moslar(matn, sorov) {
const natija = [];
if (sorov === "") return natija;
const kichik = matn.toLowerCase();
const izla = sorov.toLowerCase();
let joy = kichik.indexOf(izla);
while (joy !== -1) {
natija.push([joy, joy + izla.length]);
joy = kichik.indexOf(izla, joy + izla.length);
}
return natija;
}
function BelgilanganMatn({ matn, sorov }) {
const qismlar = [];
let joy = 0;
for (const [boshi, oxiri] of moslar(matn, sorov)) {
qismlar.push(matn.slice(joy, boshi));
qismlar.push(<mark key={boshi}>{matn.slice(boshi, oxiri)}</mark>);
joy = oxiri;
}
qismlar.push(matn.slice(joy));
return <>{qismlar}</>;
}
function App() {
return (
<ul>
<li><BelgilanganMatn matn="Non olish #bozor" sorov="NON" /></li>
<li>
<BelgilanganMatn matn="Osh, osh va yana osh" sorov="osh" />
</li>
<li><BelgilanganMatn matn="Choy damlash" sorov="" /></li>
</ul>
);
}Ekranda:
Non olish #bozor
Osh, osh va yana osh
Choy damlashEkran matnida <mark> ko'rinmaydi — u inline teg, matn o'sha. «Ishga tushir» natija oynasida esa mos bo'laklar sariq fon bilan ajralib turadi.
7.2 OddiyQator — katak, yorliq, ikki tugma
src/OddiyQator.tsx — v6 dagi oddiyQator() o'rnida. U uchta oldingi komponentni yig'adi:
// OddiyQator.tsx — katak, matn va ikki tugma (17/#06: props)
import { AmalTugmasi } from "./AmalTugmasi.tsx";
import { BelgilanganMatn } from "./BelgilanganMatn.tsx";
import { Qator } from "./Qator.tsx";
import type { VazifaMalumoti } from "./turlar.ts";
type Props = {
vazifa: VazifaMalumoti;
sorov: string;
};
export function OddiyQator({ vazifa, sorov }: Props) {
const katakId = `vazifa-${vazifa.id}`;
return (
<Qator id={vazifa.id} bajarildi={vazifa.bajarildi}>
{/* checked — holatdan (controlled). Bosilishini hozircha
vanilla ushlaydi (asosiy.ts), React'ga readOnly bilan
aytamiz: "buni men o'zgartirmayman" — #11 da onChange
keladi */}
<input
type="checkbox"
id={katakId}
data-amal="almashtir"
checked={vazifa.bajarildi}
readOnly
/>
<label htmlFor={katakId}>
<BelgilanganMatn matn={vazifa.matn} sorov={sorov} />
</label>
<AmalTugmasi
amal="tahrirla"
matn="Tahrirlash"
nomi={vazifa.matn}
/>
<AmalTugmasi amal="ochir" matn="O'chirish" nomi={vazifa.matn} />
</Qator>
);
}bajarildi={vazifa.bajarildi}—Qatorichidagi shartliclassNameni boshqaradi (children darsidagi ternary).checked+readOnly— «Shartli atributlar» bo'limidagi ogohlantirishning javobi. Izohdagi controlled (boshqariladigan) — maydon qiymatini brauzer emas, React beradi: katakvazifa.bajarildinima desa, shuni ko'rsatadi. Bu so'zni Formalar I darsida chuqur o'rganamiz. Katak holati vazifadan olinadi, bosishni esa hozircha vanilla delegatsiya ushlaydi. Hodisalarni boshqarish darsidareadOnlyo'rnigaonChangekeladi.katakId—<label htmlFor>va<input id>bog'lanishi: yorliqni bosish ham katakni bosadi. Bu id'ni e2e tekshiruv ham ishlatadi (#vazifa-1).
7.3 VazifaQatori — qaysi ko'rinish?
Va nihoyat, bugungi mavzu toza ko'rinishda — src/VazifaQatori.tsx:
// VazifaQatori.tsx — qaysi ko'rinish: tahrir yoki oddiy (17/#08)
import { OddiyQator } from "./OddiyQator.tsx";
import { TahrirQatori } from "./TahrirQatori.tsx";
import type { VazifaMalumoti } from "./turlar.ts";
type Props = {
vazifa: VazifaMalumoti;
sorov: string;
tahrirda: boolean;
};
export function VazifaQatori({ vazifa, sorov, tahrirda }: Props) {
if (tahrirda) {
return <TahrirQatori vazifa={vazifa} />;
}
return <OddiyQator vazifa={vazifa} sorov={sorov} />;
}v6 dagi qatorYasa() bilan solishtiring — mantiq aynan bir xil:
function qatorYasa(vazifa: Vazifa): HTMLLIElement {
if (vazifa.id === holat.tahrirId) {
return tahrirQatori(vazifa);
}
return oddiyQator(vazifa);
}Bitta farq bor: v6 dagi funksiya global holat.tahrirId ga o'zi qarardi. VazifaQatori esa hech narsaga "qaramaydi" — kerakli hamma narsa props bo'lib keladi (tahrirda: boolean). U Pure komponent bo'ladi: bir xil props — doim bir xil qator.
Uchala fayl tayyor, npm run tip jim tugaydi. Qatorlar hali ekranga chiqmaydi — ro'yxatni React'ga berish va commit keyingi darsda.
8. Ko'p uchraydigan xatolar
| Belgi | Sabab | Davosi |
|---|---|---|
ekranda yolg'iz 0 |
{count && …} |
count > 0 && (JSX II) |
JSX sintaksis xatosi if da |
{if (…) …} — {} ichida ko'rsatma |
ternary yoki if ni JSX'dan oldin |
| bo'sh oq ekran | yuklanish yoki xato holati chizilmagan | to'rt holatning har biriga ko'rinish |
aria-invalid="false" qoladi |
aria-* ga false berilgan |
undefined bering |
checked … without an onChange |
faqat ko'rsatiladigan katak | readOnly yoki onChange |
| ternary ichida ternary | ko'p shoxli shart JSX ichida | o'zgaruvchiga chiqaring |
9. Mashqlar
Mashqlar kurs/mashqlar/17/08-shartli-render/ da. Har yechimni «Ishga tushir» bilan sinang.
1-mashq (oson): qaysi qator chiqadi?
function Info({ guests, note, isOpen }) {
return (
<div>
<p>A: {isOpen ? "ochiq" : "yopiq"}</p>
<p>B: {guests && `${guests} mehmon`}</p>
<p>C: {guests > 0 && `${guests} mehmon`}</p>
<p>D: {note ?? "izoh yo'q"}</p>
</div>
);
}
function App() {
return <Info guests={0} note={null} isOpen={false} />;
}- B qatorida,
B:dan keyin: - D qatorida,
D:dan keyin:
Yechim
Ekranda:
A: yopiq
B: 0
C:
D: izoh yo'qB — 0 && … → 0, ko'rinadi. C — 0 > 0 → false, hech narsa. D — ?? faqat null/undefined da o'ng tomonni oladi (?? va ?.).
2-mashq (o'rta): stol band qilish holati
TableStatus komponentini yozing. Props: status — "free", "reserved" yoki "closed", va guestName (faqat reserved da beriladi). Talablar:
closed— komponent hech narsa chizmasin (null);free—<p>"Stol bo'sh" va<button>"Band qilish";reserved—<p>"Band: " va mehmon ismi qalin (<b>).
Erta return lar bilan yozing. App to'rtta stol chizsin: 1-stol bo'sh, 2-stol Malika uchun band, 3-stol yopiq, 4-stol bo'sh. Har stol oldida <h3> da raqami.
1-stol
Stol bo'sh
Band qilish
2-stol
Band: Malika
3-stol
4-stol
Stol bo'sh
Band qilishYechim
function TableStatus({ status, guestName }) {
if (status === "closed") {
return null;
}
if (status === "reserved") {
return (
<p>
Band: <b>{guestName}</b>
</p>
);
}
return (
<>
<p>Stol bo'sh</p>
<button type="button">Band qilish</button>
</>
);
}
function App() {
return (
<section>
<h3>1-stol</h3>
<TableStatus status="free" />
<h3>2-stol</h3>
<TableStatus status="reserved" guestName="Malika" />
<h3>3-stol</h3>
<TableStatus status="closed" />
<h3>4-stol</h3>
<TableStatus status="free" />
</section>
);
}Ekranda:
1-stol
Stol bo'sh
Band qilish
2-stol
Band: Malika
3-stol
4-stol
Stol bo'sh
Band qilishfree — oxirgi return, "asosiy" holat. Tugma <p> dan keyin yangi qatorda chiqdi: oldidagi <p> blok element. 3-stolda sarlavha qoldi, komponent esa hech narsa chizmadi. Sarlavhani ham yashirish kerak bo'lsa, shartni otaga ko'chirish kerak — «null — "hech narsa chizma"» bo'limidagi jadval.
3-mashq (qiyin): to'lov holati (TypeScript)
Click/Payme orqali to'lov sahifasi uchun PaymentState turini va PaymentStatus komponentini .tsx da yozing:
{ kind: "idle" }— "To'lov kutilmoqda";{ kind: "processing"; seconds: number }— "Tekshirilmoqda… (N s)";{ kind: "failed"; reason: string }—role="alert"li paragrafda "Rad etildi: " va sabab;{ kind: "paid"; amount: number; items: number }— "To'landi: 70000 so'm". Yonidaitems > 1bo'lsa " (2 ta taom)" qo'shimchasi. Tuzoqqa e'tibor:items && …emas.
switch va never bilan yozing. App beshta holatni chizsin: idle; processing 3; failed "kartada mablag' yetarli emas"; paid 70000 / 2; paid 5000 / 1.
To'lov kutilmoqda
Tekshirilmoqda… (3 s)
Rad etildi: kartada mablag' yetarli emas
To'landi: 70000 so'm (2 ta taom)
To'landi: 5000 so'mIshora: «TypeScript bilan: birorta holat unutilmasin» bo'limidagi OrderList — namuna.
Yechim
type PaymentState =
| { kind: "idle" }
| { kind: "processing"; seconds: number }
| { kind: "failed"; reason: string }
| { kind: "paid"; amount: number; items: number };
function PaymentStatus({ state }: { state: PaymentState }) {
switch (state.kind) {
case "idle":
return <p>To'lov kutilmoqda</p>;
case "processing":
return <p>Tekshirilmoqda… ({state.seconds} s)</p>;
case "failed":
return <p role="alert">Rad etildi: {state.reason}</p>;
case "paid":
return (
<p>
To'landi: {state.amount} so'm
{state.items > 1 && ` (${state.items} ta taom)`}
</p>
);
default: {
const unhandled: never = state;
return unhandled;
}
}
}
export default function App() {
return (
<>
<PaymentStatus state={{ kind: "idle" }} />
<PaymentStatus state={{ kind: "processing", seconds: 3 }} />
<PaymentStatus
state={{
kind: "failed",
reason: "kartada mablag' yetarli emas",
}}
/>
<PaymentStatus
state={{ kind: "paid", amount: 70000, items: 2 }}
/>
<PaymentStatus
state={{ kind: "paid", amount: 5000, items: 1 }}
/>
</>
);
}Ekranda:
To'lov kutilmoqda
Tekshirilmoqda… (3 s)
Rad etildi: kartada mablag' yetarli emas
To'landi: 70000 so'm (2 ta taom)
To'landi: 5000 so'm{state.items > 1 && …} — taqqoslash, shuning uchun items: 1 da hech narsa qo'shilmadi. items && … bo'lsa, items: 0 da 0 chiqib qolardi. never tekshiruvini sinab ko'ring: turga { kind: "refunded" } qo'shing — tsc default dagi qatorda xato beradi, chunki refunded never ga sig'maydi.
4-mashq: Vazifalar qadami
refactor/royxat-react branch'ida src/BelgilanganMatn.tsx, src/OddiyQator.tsx va src/VazifaQatori.tsx ni «Vazifalar qadami» bo'limidagidek yozing. npm run tip va npm run lint toza bo'lsin. Savol: OddiyQator dagi readOnly ni olib tashlasangiz, nima o'zgaradi?
Yechim
tsc va ESLint hech narsa demaydi — readOnly ixtiyoriy atribut. Lekin ro'yxat React'da chizila boshlagach (Ro'yxatlar va key), dev rejimda ogohlantirish chiqadi. Brauzer konsolida «Shartli atributlar» bo'limidagi xabar paydo bo'ladi: You provided a `checked` prop to a form field without an `onChange` handler… — har katak uchun. readOnly React'ga "bu katakni ataylab faqat ko'rsataman" deydi. Hodisalarni boshqarish darsida onChange paydo bo'lganda u o'chiriladi.
10. Real ishda
- Har ma'lumot so'rovi to'rt holatli — yuklanmoqda, xato, bo'sh va tayyor. Kod ko'rigida birinchi tekshiriladi: "Internet uzilsa nima ko'rinadi?". Keyingi qismlarda TanStack Query kabi kutubxonalar bu holatlarni tayyor beradi — lekin chizish baribir sizning ishingiz.
- Discriminated union +
never— katta loyihalarda holatlarni unutmaslikning standart usuli. TypeScript'li React jamoalarida keng tarqalgan. - Bo'sh holat — UX dizaynerlarning alohida mavzusi ("empty state"): bo'sh ro'yxat o'rniga "Hali buyurtma yo'q. Menyuga o'ting!" va tugma — foydalanuvchini keyingi qadamga boshlaydi.
- Intervyu savollari: "Shartli render usullari qaysilar?", "
{count && <X/>}nima uchun xavfli?", "Komponentnullqaytarsa nima bo'ladi?".
Xulosa
- Shart — oddiy JavaScript:
if+ ertareturn(butun ko'rinish), ternary (ikkidan biri),&&(bor yoki yo'q). &&chapida son bo'lmasin:count > 0 &&. Batafsil — JSX II.null— "hech narsa chizma"; yashirish qarorini ko'pincha ota qilgani tushunarliroq.- Murakkab shartni
returndan oldin o'zgaruvchiga chiqaring — ichma-ich ternary yozmang. - Ma'lumotli joy to'rt holatli: yuklanmoqda, xato, bo'sh, tayyor; TypeScript'da discriminated union va
neverbilan. vazifalardaVazifaQatori—qatorYasa()ning React nusxasi:tahrirdabo'lsaTahrirQatori, aks holdaOddiyQator.
Keyingi dars: Ro'yxatlarni render qilish va key — map bilan ro'yxat chizamiz, key nega va qanday tanlanishini ko'ramiz va vazifalar ro'yxatini React'ga beramiz.
Manbalar
- React: "Conditional Rendering" — react.dev/learn/conditional-rendering
- React:
<input>— "Controlling an input with a state variable",readOnly— react.dev/reference/react-dom/components/input - TypeScript Handbook: "Discriminated Unions", "Exhaustiveness checking" — typescriptlang.org/docs/handbook/2/narrowing.html
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!