IlmHamroh
JavaScript Full-stack/17-qism. React asoslari5/45-dars21 daqiqa
Mundarija (32)

Komponentlar: yaratish, nomlash va fayllarga ajratish — PascalCase, export va "ichma-ich komponent" tuzog'i

Qisqacha: React komponenti — JSX qaytaradigan oddiy funksiya, nomi katta harf bilan (PascalCase): function MenuCard() { return <li>…</li>; }. Uni teg kabi ishlatasiz — <MenuCard />, chaqirishni React o'zi qiladi. Odatda har komponent o'z .tsx faylida turadi va export function (named export) bilan chiqariladi. Komponentni boshqa komponent ichida e'lon qilmang: har chizishda u "yangi tur" bo'lib qoladi va React uning DOM'ini o'chirib, qaytadan yasaydi — yozilgan matn yo'qoladi.

Bu darsda

  • Bir sahifani ma'noli bo'laklarga — komponentlarga — ajrata olasiz.
  • Komponent nomini to'g'ri tanlaysiz va kichik harf nega ishlamasligini tushuntira olasiz.
  • Komponentni alohida faylga chiqarasiz: named va default export farqini bilasiz, import xatolarini taniysiz.
  • Komponent nimani qaytara olishini bilasiz: JSX, null, matn, son, massiv.
  • "Komponent ichida komponent" tuzog'ini jonli ko'rib, uni lint qoidasi bilan ushlaysiz.

Oldin bilishingiz kerak: JSX II: ifodalar, Fragment va nima ekranga chiqadi, JSX I: JSX aslida JavaScript, Nega modullar va ESM export.

1. Nega bu kerak?

JSX II darsida hamma kodni bitta App ichiga yozdik. Kichik misolda bu qulay. Lekin «Bahor» saytining bosh sahifasini tasavvur qiling: sarlavha, ish vaqti, menyu, aloqa, pastki qism. Hammasi bitta funksiyada bo'lsa — 200 qatorli return. Qaysi qavs nimani yopayotganini topish qiyin, menyu kartasi o'n joyda takrorlanadi.

Vanilla'da bu muammoni allaqachon yechgansiz. vazifalar dagi render.ts da oddiyQator(), tahrirQatori(), tugmaYasa() funksiyalari bor. Har biri bitta bo'lakni yasab qaytaradi. Katta ekran — kichik funksiyalar yig'indisi.

React'da g'oya o'sha, faqat funksiya DOM elementini emas, JSX qaytaradi. Bunday funksiya komponent deyiladi. Hayotiy o'xshatish: oshxonadagi retseptlar daftari. Osh retsepti bir sahifada yozilgan, oshpaz uni har kuni qayta ishlatadi va har safar boshqatdan o'ylab topmaydi. Menyu kartasi ham shunday: bir marta yozasiz, kerakli joyga qo'yasiz.

2. Birinchi o'z komponentimiz

2.1 Bitta katta App dan bo'laklarga

Avval «Bahor» bosh sahifasi — hammasi bitta joyda:

jsx
function App() {
  return (
    <div>
      <header>
        <h1>«Bahor» oshxonasi</h1>
        <p>Toshkent, Chilonzor</p>
      </header>
      <p>Ish vaqti: 07:00–23:00</p>
      <footer>
        <p>Tel: +998 90 000 00 00</p>
      </footer>
    </div>
  );
}

Ekranda:

text
«Bahor» oshxonasi
Toshkent, Chilonzor
Ish vaqti: 07:00–23:00
Tel: +998 90 000 00 00

Endi har ma'noli bo'lakni o'z funksiyasiga olib chiqamiz:

jsx
function SiteHeader() {
  return (
    <header>
      <h1>«Bahor» oshxonasi</h1>
      <p>Toshkent, Chilonzor</p>
    </header>
  );
}

function WorkHours() {
  return <p>Ish vaqti: 07:00–23:00</p>;
}

function SiteFooter() {
  return (
    <footer>
      <p>Tel: +998 90 000 00 00</p>
    </footer>
  );
}

function App() {
  return (
    <div>
      <SiteHeader />
      <WorkHours />
      <SiteFooter />
    </div>
  );
}

Ekranda:

text
«Bahor» oshxonasi
Toshkent, Chilonzor
Ish vaqti: 07:00–23:00
Tel: +998 90 000 00 00

Ekran o'zgarmadi — bu yaxshi belgi. Endi App ni o'qish oson: uch qator, uchta bo'lak. Sarlavhani o'zgartirmoqchi bo'lsangiz — SiteHeader ni ochasiz, qolganiga tegmaysiz.

Uch qoida ko'rinib turibdi:

  1. Komponent — oddiy function, hech qanday maxsus kalit so'z yo'q.
  2. U JSX qaytaradi — return bilan.
  3. Uni teg kabi ishlatamiz: <SiteHeader />. Ichida hech narsa bo'lmasa — o'zini yopuvchi teg (/>), JSX I dagidek.

2.2 Komponentni React chaqiradi

<SiteHeader /> yozganingizda SiteHeader hali chaqirilmaydi. JSX I darsida ko'rdik: bu jsx(SiteHeader, {}) ga aylanadi va oddiy obyekt yasaydi — type maydonida funksiyaning o'zi turadi. Funksiyani keyin React chaqiradi, ekranga chizish vaqti kelganda.

Farqni kod bilan ko'ramiz. console.log funksiya qachon ishlaganini ko'rsatadi:

jsx
function WorkHours() {
  console.log("WorkHours chaqirildi");
  return <p>Ish vaqti: 07:00–23:00</p>;
}

const element = <WorkHours />;
console.log("Element tayyor:", typeof element.type);

function App() {
  return element;
}

Konsolda:

text
Element tayyor: function
WorkHours chaqirildi

Ekranda:

text
Ish vaqti: 07:00–23:00

Avval "Element tayyor" chiqdi: <WorkHours /> faqat "buyurtma qog'ozi" yasadi. "WorkHours chaqirildi" esa keyin — React App ni chizayotganda. Komponentni o'zingiz WorkHours() deb chaqirmang. Hozircha ekran bir xil chiqadi, lekin React uni alohida komponent deb tanimaydi. useState darsidan boshlab bu haqiqiy xatoga aylanadi (Hooklar qoidalari darsida sababi).

2.3 Arrow funksiya ham komponent

Komponent function bilan ham, arrow funksiya bilan ham yoziladi:

jsx
const WorkHours = () => <p>Ish vaqti: 07:00–23:00</p>;

function App() {
  return <WorkHours />;
}

Ekranda:

text
Ish vaqti: 07:00–23:00

React uchun farqi yo'q. Bu kursda va vazifalar da function ishlatamiz. U faylning istalgan joyidan ko'rinadi (hoisting): App ni yuqoriga, yordamchi komponentlarni pastga yozish mumkin. React rasmiy hujjatlari ham function bilan yozadi.

Tekshirib ko'ring: const a = <SiteHeader />; qatori bajarilganda SiteHeader funksiyasi necha marta chaqiriladi?

Javob

Nol marta. JSX faqat element obyektini yasaydi: { type: SiteHeader, props: {} }. Funksiyani React chaqiradi — element ekranga chizilganda. Element hech qachon chizilmasa (masalan, o'zgaruvchida qolib ketsa), funksiya umuman chaqirilmaydi.

3. Komponent nimani qaytaradi

3.1 JSX, matn, son, null, massiv

Komponent qaytaradigan qiymatga JSX II dagi {} qoidalari amal qiladi. Ya'ni {} ichiga nima qo'ysangiz bo'lsa, komponent shuni qaytara oladi:

jsx
function Price() {
  return 35000;
}

function Nothing() {
  return null;
}

function Pair() {
  return [<b key="osh">Osh</b>, " va ", <i key="choy">choy</i>];
}

function Greeting() {
  return "Xush kelibsiz!";
}

function App() {
  return (
    <div>
      <p><Price /> so'm</p>
      <p>[<Nothing />]</p>
      <p><Pair /></p>
      <p><Greeting /></p>
    </div>
  );
}

Ekranda:

text
35000 so'm
[]
Osh va choy
Xush kelibsiz!

null — "bu komponent hozir hech narsa chizmaydi". Masalan, aksiya tugaganda aksiya bannerini yashirish uchun. Bu usulni Shartli render darsida ko'p ishlatamiz. Massiv o'rniga odatda Fragment yoziladi (<>…</>) — unda key kerak emas.

3.2 return unutilsa

Arrow funksiyadan function ga o'tganda ko'p uchraydigan xato:

jsx
function SiteHeader() {
  <h1>«Bahor» oshxonasi</h1>;
}

function App() {
  return (
    <div>
      <SiteHeader />
      <p>Ish vaqti: 07:00–23:00</p>
    </div>
  );
}

Ekranda:

text
Ish vaqti: 07:00–23:00

Sarlavha yo'q, konsolda ham hech narsa yo'q. JSX hisoblandi va tashlab yuborildi, funksiya esa undefined qaytardi. React 19 undefined ni "hech narsa" deb qabul qiladi — xuddi null kabi. Shuning uchun bu xato jim o'tadi.

TypeScript esa uni ushlaydi:

tsx
function SiteHeader() {
  <h1>«Bahor» oshxonasi</h1>;
}

export function App() {
  return <SiteHeader />;
}

Xato:

text
TS2786: 'SiteHeader' cannot be used as a JSX component.
  Its type '() => void' is not a valid JSX element type.
    Type '() => void' is not assignable to type '(props: any) => Promise<ReactNode> | ReactNode'.
      Type 'void' is not assignable to type 'Promise<ReactNode> | ReactNode'.

Tarjima: "SiteHeader ni JSX komponenti sifatida ishlatib bo'lmaydi. Uning turi — void (hech narsa) qaytaradigan funksiya." Oxirgi qator asosiysi: "void turini ReactNode ga berib bo'lmaydi". JSX II darsidagi ReactNode — komponent qaytarishi mumkin bo'lgan qiymatlar, void esa unda yo'q. Bu — vazifalar dagidek .tsx da yozishning yana bir foydasi.

Maslahat: Qavsli arrow funksiya () => (<h1>…</h1>) JSX'ni o'zi qaytaradi. Jingalak qavsli () => { <h1>…</h1> } esa qaytarmaydi — xuddi yuqoridagi xato.

4. Nomlash: PascalCase

4.1 Kichik harf — HTML teg

React nima va nega darsida kichik harfli menuCard ni sinab ko'rgan edik. Natija — ekran bo'sh va konsolda ikki ogohlantirish:

jsx
function workHours() {
  return <p>Ish vaqti: 07:00–23:00</p>;
}

function App() {
  return <workHours />;
}

Konsolda:

text
<workHours /> is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements.
The tag <workHours> is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter.

Ekranda:

text
(bo'sh)

Sababi transpilerda (JSX I): kichik harfli teg satrga aylanadi — jsx("workHours", {}). React brauzerdan <workhours> elementini so'radi. Bunday HTML teg yo'q — bo'sh noma'lum element chiqdi, funksiya esa umuman chaqirilmadi. Katta harfli <WorkHours /> esa o'zgaruvchiga aylanadi — jsx(WorkHours, {}).

4.2 Yaxshi nom qanday bo'ladi

PascalCase — har so'z katta harf bilan, orada bo'shliq va chiziqcha yo'q: MenuCard, SiteHeader, OrderList. Bundan tashqari:

Qoida
Ot — "nima chiziladi" OrderList RenderOrders, ShowList
Ma'noli, qisqartmasiz WorkHours WH, Comp1
Bo'lak nomi ota nomidan MenuCard, MenuList Card2
Fayl nomi = komponent nomi MenuCard.tsx card.tsx

Kursda funksiyalarni fe'l bilan nomlaymiz (narxniHisobla). Komponent esa istisno: u ishni bajarmaydi, ekran bo'lagini tasvirlaydi. Shuning uchun nomi — ot. vazifalar da komponent nomlari o'zbekcha: VazifaQatori, AmalTugmasi, VazifaRoyxati — qoida o'sha.

Tekshirib ko'ring: Qaysilari ishlaydi? <Menu_card />, <MENU />, <menuCard />, <Menu2 />.

Javob

Kichik harfli <menuCard /> dan boshqa hammasi komponent sifatida ishlaydi: React faqat birinchi harfga qaraydi. Lekin Menu_card va MENU — PascalCase emas, kod ko'rigida qaytariladi. Menu2 ishlaydi, lekin ma'nosiz nom.

5. Komponentlar daraxti

Bo'laklar bir-birining ichiga joylashadi. «Bahor» menyu sahifasini daraxt qilib chizamiz:

flowchart TD
  App --> SiteHeader
  App --> MenuList
  App --> SiteFooter
  MenuList --> C1["MenuCard (Osh)"]
  MenuList --> C2["MenuCard (Manti)"]
  MenuList --> C3["MenuCard (Choy)"]

Rasmga qarang: yuqorida App, undan pastga bolalari. Bu yerda App boshqa komponentlarni chizadi — u ularning ota komponenti (parent). Uning bola komponentlari (children) esa SiteHeader, MenuList va SiteFooter. Diqqat qiling: MenuCard uch marta uchraydi — bitta funksiya, uch nusxa. Bu daraxt DOM daraxti dan bir pog'ona yuqorida turadi: bitta MenuCard ichida bir nechta DOM elementi bo'lishi mumkin.

Daraxtning foydasi: ma'lumot yuqoridan pastga oqadi. Keyingi darsda MenuList har MenuCard ga o'z taomini props orqali beradi. Hozircha har bola o'z ichidagini o'zi biladi.

6. Komponentni alohida faylga chiqarish

6.1 Bir fayl — bir komponent

Birinchi React loyiha darsidagi bahor-menyu loyihasini davom ettiramiz. Kichik loyihada komponentlar src/ ichida, kattaroqda — src/components/ papkasida:

text
src/
├── main.tsx           ← createRoot(...).render(<App />)
├── App.tsx            ← sahifa: bo'laklarni yig'adi
└── components/
    ├── SiteHeader.tsx
    ├── WorkHours.tsx
    └── SiteFooter.tsx

Har fayl — bitta komponent va uning nomi bilan:

tsx
// src/components/WorkHours.tsx
export function WorkHours() {
  return <p>Ish vaqti: 07:00–23:00</p>;
}

App.tsx ularni import qilib yig'adi:

tsx
// src/App.tsx
import { SiteHeader } from "./components/SiteHeader.tsx";
import { WorkHours } from "./components/WorkHours.tsx";
import { SiteFooter } from "./components/SiteFooter.tsx";

export default function App() {
  return (
    <div>
      <SiteHeader />
      <WorkHours />
      <SiteFooter />
    </div>
  );
}

Bu ikki blokda «Ishga tushir» yo'q: ular bir-birini fayl orqali import qiladi, natija oynasi esa bitta blokni bajaradi. Shu fayllarni o'z loyihangizda yarating — npm run dev da ekran «Bitta katta App dan bo'laklarga» bo'limidagi bilan bir xil chiqadi.

Nega har komponent alohida faylda:

  • Topish oson — WorkHours.tsx nomidan ichida nima borligi ko'rinadi.
  • Git tarixi toza — sarlavha o'zgarsa, faqat bitta fayl o'zgaradi (git diff kichik va tushunarli).
  • Fast Refresh ishlaydi (Birinchi React loyiha): faqat komponent eksport qiladigan fayl tahrirlanganda sahifa qayta yuklanmaydi.

6.2 Named va default export

Modullar darsidagi ikki xil export komponentlarda ham bor:

Named export Default export
Yozilishi export function MenuCard() export default function App()
Import import { MenuCard } from "…" import App from "…"
Nom aynan bir xil bo'lishi shart import qiluvchi istagancha ataydi
Faylda bir nechta bo'lishi mumkin faqat bitta

Vite shablonida App — default export. vazifalar da va bu kursda komponentlar — named export. Sababi: nom hamma joyda bir xil bo'ladi. Default bilan bir fayl import Card from …, boshqasi import MenuCard from … deb yozishi mumkin. Qidiruvda ikkalasini topish qiyin, nomini o'zgartirganda biri esdan chiqadi. Default export kerak bo'ladigan joylar ham bor: React.lazy va ba'zi framework'lar (Next.js sahifalari) shuni talab qiladi — ularga keyingi qismlarda yetamiz.

6.3 Import xatolari

Eng ko'p uchraydigani — named export'ni default kabi import qilish:

tsx
// src/App.tsx — ❌ MenuCard.tsx da "export function MenuCard"
import MenuCard from "./MenuCard.tsx";

Uch joyda uch xil xabar chiqadi. Biz Vite shablonida haqiqatan sinab ko'rdik. npm run dev da brauzer konsolida (ekran bo'sh):

text
Uncaught SyntaxError: The requested module '/src/MenuCard.tsx' does not provide an export named 'default'

"So'ralgan modul default nomli eksport bermaydi." npx tsc -b da (yo'l qisqartirilgan):

text
src/App.tsx(1,8): error TS2613: Module '".../src/MenuCard"' has no default export. Did you mean to use 'import { MenuCard } from ".../src/MenuCard"' instead?

TypeScript hatto to'g'ri yozuvni ham taklif qiladi: "import { MenuCard } … demoqchimidingiz?". npm run build da Vite 8 (Rolldown):

text
[MISSING_EXPORT] "default" is not exported by "src/MenuCard.tsx".

Tuzatish — jingalak qavslar: import { MenuCard } from "./MenuCard.tsx";. Teskari xato ham bor: default'ni { App } qilib import qilish. U holda xabarda export named 'App' deyiladi.

6.4 Komponent faylida boshqa narsa eksport qilsa

Shablondagi linter (Oxlint) bitta qoidani kuzatadi. MenuCard.tsx ga narx formatlaydigan funksiya qo'shib, uni ham eksport qildik:

tsx
export function MenuCard() {
  return <li>Osh — {formatPrice(35000)}</li>;
}

export function formatPrice(price: number) {
  return `${price} so'm`;
}

npm run lint (Oxlint 1.87.0):

text
src/MenuCard.tsx:5:17: warning react(only-export-components): Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components.

"Fast Refresh faqat fayl komponentlarni eksport qilsagina ishlaydi. Komponentlar orasida umumiy konstanta yoki funksiyani yangi faylga oling." Bu xato emas, ogohlantirish: ilova ishlaydi, faqat shu faylni tahrirlaganda sahifa to'liq qayta yuklanadi. Yechim — formatPrice ni src/format.ts ga ko'chirish. .ts — chunki ichida JSX yo'q.

7. Komponent ichida komponent e'lon qilmang

7.1 Tuzoqni jonli ko'ramiz

Sardor ism maydonini alohida komponentga ajratdi va uni App ning ichiga yozdi — "u faqat shu yerda kerak-ku". Quyidagi blokda count va draw() — JSX II darsidagi vanilla usul: tugma count ni oshirib, App ni qayta chizadi. Blok o'zi maydonga "Ali" deb yozadi, keyin «+1» ni bosadi:

jsx
import { flushSync } from "react-dom";
import { createRoot } from "react-dom/client";

const root = createRoot(document.getElementById("root"));
let count = 0;

function App() {
  // ❌ komponent App ichida e'lon qilingan
  function NameField() {
    return <input aria-label="Ism" />;
  }

  return (
    <div>
      <p>Bosildi: {count}</p>
      <NameField />
      <button onClick={draw}>+1</button>
    </div>
  );
}

function draw() {
  count++;
  flushSync(() => root.render(<App />));
  const input = document.querySelector("input");
  console.log("Maydonda:", JSON.stringify(input.value));
}

flushSync(() => root.render(<App />));

Konsolda:

text
Maydonda: ""

Ekranda:

text
Bosildi: 1
+1

«Ishga tushir» ni bosing va o'zingiz sinang: maydonga yozing, «+1» ni bosing — matn yo'qoladi. Bu yerdagi flushSync — Birinchi React loyiha dagidek: chizishni darhol tugatadi, shunda keyingi qatordagi console.log yangi DOM'ni o'qiydi.

7.2 Nega yo'qoldi

Har App chaqiruvida function NameField() {…} qatori yangi funksiya yaratadi. Closure darsidan bilasiz: ikki marta yaratilgan funksiya — ikki xil obyekt, === bilan teng emas. React esa daraxtni solishtirganda avval elementning turiga (type) qaraydi:

Qadam NameField React qarori Maydonda
birinchi chizish funksiya №1 yangi <input> yasaydi ""
"Ali" yozildi — — "Ali"
«+1», qayta chizish funksiya №2 tur boshqa → eskisini o'chirib, yangisini yasaydi ""

"Tur boshqa" — React uchun "bu butunlay boshqa komponent". Eski <input> DOM'dan olib tashlanadi, o'rniga yangi, bo'sh <input> qo'yiladi. Fokus ham, yozilgan matn ham yo'qoladi. Keyingi darslarda komponentning o'z xotirasi (state) paydo bo'ladi — u ham har safar o'chadi.

Tuzatish — komponentni tashqariga, faylning yuqori darajasiga chiqarish:

jsx
import { flushSync } from "react-dom";
import { createRoot } from "react-dom/client";

const root = createRoot(document.getElementById("root"));
let count = 0;

// ✅ yuqori darajada: funksiya bir marta yaratiladi
function NameField() {
  return <input aria-label="Ism" />;
}

function App() {
  return (
    <div>
      <p>Bosildi: {count}</p>
      <NameField />
      <button onClick={draw}>+1</button>
    </div>
  );
}

function draw() {
  count++;
  flushSync(() => root.render(<App />));
  const input = document.querySelector("input");
  console.log("Maydonda:", JSON.stringify(input.value));
}

flushSync(() => root.render(<App />));

Konsolda:

text
Maydonda: "Ali"

Ekranda:

text
Bosildi: 1
+1

Endi NameField — har safar o'sha bitta funksiya. React turni bir xil ko'radi va <input> ga tegmaydi. Bu xulqning to'liq ichki ishlashi — Reconciliation va Fiber darsida.

7.3 Linter buni ushlaydi

eslint-plugin-react-hooks 7.1.1 da bu holat uchun alohida qoida bor — react-hooks/static-components. Uni vazifalar ga Birinchi React loyiha darsida ulagan edik. Mana bunday faylni tekshirdik:

jsx
// Profile.jsx — ❌ Price komponenti Profile ichida
export function Profile({ dish }) {
  function Price() {
    return <b>{dish.price} so'm</b>;
  }
  return <Price />;
}

npx eslint Profile.jsx (ESLint 10.12.0; kod parchalari qisqartirilgan, izoh qatori olib tashlangan):

text
  6:11  error  Error: Cannot create components during render

Components created during render will reset their state each time they are created. Declare components outside of render.

> 6 |   return <Price />;
    |           ^^^^^ This component is created during render

> 3 |   function Price() {
    |   ^^^^^^^^^^^^^^^^^^
    …
> 5 |   }
    | ^^^^ The component is created during render here
  react-hooks/static-components

✖ 1 problem (1 error, 0 warnings)

"Render paytida komponent yaratib bo'lmaydi. Render vaqtida yaratilgan komponentlar har safar state'ini yo'qotadi. Komponentlarni render'dan tashqarida e'lon qiling." Linter ikki joyni ko'rsatadi: qayerda ishlatilgani va qayerda yaratilgani.

Diqqat: Ichki komponentga ota komponentning o'zgaruvchisi kerak bo'lgani uchun ichkariga yozilgan bo'lishi mumkin. To'g'ri yo'l — o'sha qiymatni props bilan berish. Bu — keyingi dars.

8. Vazifalar qadami: ro'yxat komponentlari rejasi

Bu darsdan Ro'yxatlar va key darsigacha vazifalar da bitta katta ish qilamiz: vazifalar ro'yxatini React chizadi. Holat va hodisalar hozircha vanilla qoladi — React faqat <ul id="royxat"> ning ichini oladi. Hammasi bitta branch'da va besh dars oxirida bitta commit bo'ladi.

bash
git switch -c refactor/royxat-react

Bugun — reja. src/render.ts dagi vanilla funksiyalar React komponentlariga shunday mos keladi:

render.ts (v6) Komponent (fayl) Qaysi darsda
tugmaYasa() AmalTugmasi.tsx Props
li qobig'i (ikkala qatorda) Qator.tsx children
tahrirQatori() TahrirQatori.tsx children
belgilanganMatn(), oddiyQator() BelgilanganMatn.tsx, OddiyQator.tsx Shartli render
qatorYasa() VazifaQatori.tsx Shartli render
replaceChildren(...map(qatorYasa)) VazifaRoyxati.tsx Ro'yxatlar va key

Bugungi darsdan uchta qoida shu fayllarga to'g'ridan-to'g'ri o'tadi:

  • har komponent — src/ dagi o'z .tsx faylida, fayl nomi = komponent nomi;
  • export function (named export), default yo'q;
  • nomlar o'zbekcha va ot: VazifaQatori, AmalTugmasi.

Komponentlarning hammasi yuqori darajada yoziladi — bittasi ham boshqasining ichida emas. Fayllar src/ ning o'zida turadi, components/ papkasi yo'q. Papka tuzilmasini Kichik React loyihani tashkil qilish darsida tartiblaymiz.

9. Ko'p uchraydigan xatolar

Belgi Sabab Davosi
ekran bo'sh, incorrect casing komponent nomi kichik harf bilan WorkHours
komponent jim, ekranda yo'q function da return unutilgan return (…) yoki .tsx (TS2786)
does not provide an export named 'default' named export'ni default kabi import import { MenuCard }
only-export-components komponent faylida funksiya ham eksport funksiyani .ts faylga
yozilgan matn yo'qoladi komponent boshqa komponent ichida yuqori darajaga chiqaring
Cannot create components during render o'sha, linter topdi o'sha

10. Mashqlar

Mashqlar kurs/mashqlar/17/05-komponentlar/ da. 1- va 2-mashqni shu sahifadagi «Ishga tushir» bilan sinang. 3-mashq — o'z Vite loyihangizda.

1-mashq (oson): uchta xato

Sardorning kodida ekranda faqat "Ish vaqti" chiqyapti. Kodni o'zgartirmasdan, faqat o'qib, uchta xatoni toping. Keyin tuzating: ekranda sarlavha, manzil va ish vaqti chiqsin, konsol toza bo'lsin.

jsx
function siteHeader() {
  return <h1>«Bahor» oshxonasi</h1>;
}

function Address() {
  <p>Toshkent, Chilonzor</p>;
}

const WorkHours = () => {
  return <p>Ish vaqti: 07:00–23:00</p>;
};

function App() {
  return (
    <div>
      <siteHeader />
      <Address />
      <WorkHours />
    </div>
  );
}

Konsolda:

text
<siteHeader /> is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements.
The tag <siteHeader> is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter.

Ekranda:

text
Ish vaqti: 07:00–23:00

Birinchi xato — e'londa: nomi kichik harf bilan.

Yechim
jsx
function SiteHeader() {
  return <h1>«Bahor» oshxonasi</h1>;
}

function Address() {
  return <p>Toshkent, Chilonzor</p>;
}

const WorkHours = () => {
  return <p>Ish vaqti: 07:00–23:00</p>;
};

function App() {
  return (
    <div>
      <SiteHeader />
      <Address />
      <WorkHours />
    </div>
  );
}

Ekranda:

text
«Bahor» oshxonasi
Toshkent, Chilonzor
Ish vaqti: 07:00–23:00
  1. siteHeader — kichik harf: React uni HTML teg deb oldi. E'londa ham, ishlatishda ham SiteHeader.
  2. Address da return yo'q — jim xato, konsolda hech narsa chiqmaydi.
  3. Uchinchi "xato" aslida xato emas: WorkHours — arrow funksiya, return bilan. U to'g'ri ishlaydi. Ba'zan "xato" deb shubha qilingan joy to'g'ri bo'ladi — buni kodni ishga tushirib bilasiz.

2-mashq (o'rta): menyu sahifasini bo'laklang

Quyidagi App ni to'rtta komponentga ajrating: SiteHeader, MenuList, MenuCard (bitta taom, ichida hozircha "Osh — 35000 so'm"), SiteFooter. MenuList ichida MenuCard uch marta ishlatilsin. Ekran shunday bo'lsin:

text
«Bahor» menyusi
Osh — 35000 so'm
Osh — 35000 so'm
Osh — 35000 so'm
Buyurtma: +998 90 000 00 00

Ishora: «Bitta katta App dan bo'laklarga» bo'limidagi kodni namuna qiling. Uch karta bir xil chiqyapti — har kartaga o'z taomini berish keyingi darsning mavzusi.

Yechim
jsx
function SiteHeader() {
  return <h1>«Bahor» menyusi</h1>;
}

function MenuCard() {
  return <li>Osh — 35000 so'm</li>;
}

function MenuList() {
  return (
    <ul>
      <MenuCard />
      <MenuCard />
      <MenuCard />
    </ul>
  );
}

function SiteFooter() {
  return (
    <footer>
      <p>Buyurtma: +998 90 000 00 00</p>
    </footer>
  );
}

function App() {
  return (
    <main>
      <SiteHeader />
      <MenuList />
      <SiteFooter />
    </main>
  );
}

Ekranda:

text
«Bahor» menyusi
Osh — 35000 so'm
Osh — 35000 so'm
Osh — 35000 so'm
Buyurtma: +998 90 000 00 00

MenuCard uch marta qo'lda yozilgan, .map() bilan emas — shuning uchun key kerak emas (JSX I dagi jsxs). Daraxt: App → SiteHeader, MenuList → 3 × MenuCard, SiteFooter.

3-mashq (qiyin): fayllarga ajrating va tuzoqni tuzating

Birinchi React loyiha darsidagi bahor-menyu loyihangizda (yoki yangi npm create vite@9.2.1 … --template react-ts):

  1. 2-mashqdagi to'rtta komponentni src/components/ dagi to'rtta faylga chiqaring — har biri named export.
  2. App.tsx ularni import qilsin, o'zi default export qolsin (main.tsx shuni kutadi).
  3. src/components/SearchBox.tsx yarating: <input aria-label="Taom qidirish" />. Sardor uni MenuList ichida e'lon qilib yuborgan edi — siz uni o'z faylida yozing va MenuList ning tepasida ishlating.
  4. npx tsc -b va npm run lint toza bo'lsin.
Yechim
tsx
// src/components/SearchBox.tsx
export function SearchBox() {
  return <input aria-label="Taom qidirish" />;
}
tsx
// src/components/MenuList.tsx
import { MenuCard } from "./MenuCard.tsx";
import { SearchBox } from "./SearchBox.tsx";

export function MenuList() {
  return (
    <section>
      <SearchBox />
      <ul>
        <MenuCard />
        <MenuCard />
        <MenuCard />
      </ul>
    </section>
  );
}
tsx
// src/App.tsx
import { MenuList } from "./components/MenuList.tsx";
import { SiteFooter } from "./components/SiteFooter.tsx";
import { SiteHeader } from "./components/SiteHeader.tsx";

export default function App() {
  return (
    <main>
      <SiteHeader />
      <MenuList />
      <SiteFooter />
    </main>
  );
}

SiteHeader.tsx, MenuCard.tsx, SiteFooter.tsx — 2-mashqdagi funksiyalar, oldiga export qo'shilgan. Tekshiruv ro'yxati:

  • npx tsc -b jim tugaydi. TS2613 chiqsa — qaysidir importda jingalak qavs unutilgan.
  • npm run lint jim. only-export-components chiqsa — komponent faylida boshqa narsa ham eksport qilingan.
  • Brauzerda qidiruv maydoniga yozing va MenuCard.tsx dagi narxni o'zgartirib saqlang. Fast Refresh sahifani yangilaydi, lekin maydondagi matn joyida qoladi.

4-mashq: Vazifalar qadami

vazifalar da refactor/royxat-react branch'ini yarating. src/render.ts ni ochib, «Vazifalar qadami» bo'limidagi jadvalni o'zingiz tekshiring: har vanilla funksiya qaysi komponentga aylanadi? Bitta savolga yozma javob bering: nega belgilanganMatn() ham alohida komponent bo'ladi, oddiy funksiya qolmaydi?

Yechim

belgilanganMatn() vanilla'da <mark> elementlarini yasaydi — ya'ni u ekran bo'lagini qaytaradi. React'da ekran bo'lagini qaytaradigan funksiya — komponent. BelgilanganMatn JSX qaytaradi va ichida <mark> lar ro'yxati bo'ladi. Aksincha, moslar() (qidiruv.ts) faqat raqamlar (oraliqlar) qaytaradi — u oddiy funksiya bo'lib qoladi va node:test testlari o'zgarmaydi. Qoida: DOM yoki JSX qaytarsa — komponent, ma'lumot qaytarsa — oddiy funksiya.

Kod bugun o'zgarmaydi. Commit Ro'yxatlar va key darsida bo'ladi.

11. Real ishda

  • Begona loyihada birinchi qaraladigan joy — komponentlar daraxti. React DevTools uni brauzerda ko'rsatadi (React DevTools).
  • Kod ko'rigida (code review) ichki komponent e'loni va return siz komponent — tez topiladigan xatolar. Bugun buni linter o'zi ushlaydi.
  • Kompaniyalarda "bir fayl — bir komponent" va named export odatda jamoa qoidasi: ESLint yoki Oxlint sozlamasida yozilgan bo'ladi.
  • Intervyu savollari: "Komponent nima va oddiy funksiyadan farqi?", "Nega nom katta harf bilan?". Yana biri: "Komponentni boshqa komponent ichida e'lon qilsa nima bo'ladi?". Va: "Named yoki default export — qaysi birini tanlaysiz?".

Xulosa

  • Komponent — JSX (yoki null, matn, son) qaytaradigan funksiya; uni <Nom /> bilan ishlatasiz, chaqirishni React qiladi.
  • Nom — PascalCase va ot: kichik harfli teg HTML teg deb olinadi, funksiya chaqirilmaydi.
  • return unutilsa komponent jim yo'qoladi; TypeScript buni TS2786 bilan ushlaydi.
  • Bir fayl — bir komponent, named export; App — shablondagidek default.
  • Komponentni boshqa komponent ichida e'lon qilmang: har chizishda yangi tur — DOM va kiritilgan matn yo'qoladi.
  • vazifalar da ro'yxatni React'ga berish boshlandi: reja va refactor/royxat-react branch'i.

Keyingi dars: Props: komponentga ma'lumot uzatish — MenuCard ga taom nomi va narxini tashqaridan beramiz va vazifalar dagi birinchi ikki komponentni yozamiz.

Manbalar

  • React: "Your First Component", "Importing and Exporting Components" — react.dev/learn
  • React: "Nesting and organizing components", "Components and Hooks must be pure" — react.dev/learn, react.dev/reference/rules
  • eslint-plugin-react-hooks — static-components qoidasi — react.dev/reference/eslint-plugin-react-hooks
  • Oxlint: react/only-export-components — oxc.rs/docs/guide/usage/linter/rules
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Komponentlar: yaratish, nomlash va fayllarga ajratish — PascalCase, export va "ichma-ich komponent" tuzog'i — IlmHamroh