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

JSX I: JSX aslida JavaScript — jsx() chaqiruvi va yozish qoidalari

Qisqacha: JSX — JavaScript ichida HTML'ga o'xshatib yoziladigan sintaksis. Brauzer uni bilmaydi: transpiler har <teg> ni jsx("teg", { ...props }) chaqiruviga aylantiradi, natijasi esa oddiy JavaScript obyekti — React elementi. JSX'ning hamma "g'alati" qoidasi shundan kelib chiqadi: bitta ildiz (funksiya bitta qiymat qaytaradi), className va htmlFor (DOM xususiyatlari nomi), camelCase atributlar va obyekt ko'rinishidagi style.

Bu darsda

  • JSX'ga qarab, u qaysi jsx() yoki jsxs() chaqiruviga aylanishini ayta olasiz.
  • React elementi oddiy obyekt ekanini konsolda ko'rasiz va JSX'siz ham ekranga ro'yxat chiqarasiz.
  • HTML'ni JSX'ga to'g'ri o'girasiz: yopiq teglar, className, htmlFor, camelCase, style obyekti.
  • {} ichiga ifoda qo'yasiz va nega u yerga if sig'masligini tushuntirasiz.
  • Saytdagi, Vite'dagi va tsc dagi JSX xato xabarlarini o'qiy olasiz.

Oldin bilishingiz kerak: Birinchi React loyiha, Transpilyatsiya: Babel, SWC, esbuild va Oxc, Atributlar, xususiyatlar va dataset.

1. Nega bu kerak?

Birinchi React loyiha darsida App.tsx ni ochdingiz. Funksiya ichida return (<div>…</div>) turibdi. JavaScript fayl ichida HTML? Bu qanday ishlaydi?

Javobning yarmini 16-qismda ko'rgansiz. Transpilyatsiya darsida to'rt transpiler <li className="taom"> ni _jsxs("li", {…}) ga aylantirdi. O'shanda "React — 17-qismda, hozir faqat sintaksis muhim" degan edik. Bugun shu chaqiruvning ichiga kiramiz.

Sardor «Bahor» menyusini React'da yozyapti. Birinchi soatda uchta xatoga duch keldi:

  • <img src="osh.jpg"> — ekranda qizil quti: Unterminated JSX contents.
  • <label for="ism"> — konsolda: Invalid DOM property 'for'.
  • style="color: green" — butun komponent yiqildi.

Uchalasining sababi bitta: JSX — HTML emas, u JavaScript. Buni tushunsangiz, qoidalarni yodlash shart emas — ular o'z-o'zidan kelib chiqadi.

Hayotiy o'xshatish: stenografiya. Kotib qisqa belgilar bilan yozadi, keyin ularni to'liq matnga ochadi. JSX ham qisqa yozuv: <h1>Menyu</h1> aslida jsx("h1", { children: "Menyu" }). Qisqa yozuvning har qoidasi to'liq yozuvdan kelib chiqadi.

2. JSX nimaga aylanadi

2.1 Bitta fayl — esbuild bilan

JSX (JavaScript XML) — JavaScript'ning kengaytmasi: kod ichida teglar yozish imkonini beradi. Uni React jamoasi 2013-yilda o'ylab topgan. JavaScript standartida JSX yo'q — shuning uchun brauzer ham, Node ham uni to'g'ridan-to'g'ri bajara olmaydi.

Tekshirib ko'ramiz. Menu.jsx faylida bir nechta JSX bor (price va MenuCard boshqa joyda e'lon qilingan deb hisoblaymiz):

jsx
const title = <h1 className="sarlavha">Menyu</h1>;
const item = <li id="osh">Osh: {price} so'm</li>;
const label = <label htmlFor="ism">Ismingiz</label>;
const off = <button disabled>Tugadi</button>;
const card = <MenuCard name="Osh" price={price} />;
const row = <li key="osh">Osh</li>;
const list = (
  <ul>
    <li>Osh</li>
    <li>Manti</li>
  </ul>
);

Uni esbuild 0.28.2 bilan o'giramiz (16-qismdagi kabi; --charset=utf8 — o'zbekcha harflar escape qilinmasin):

bash
npx esbuild@0.28.2 Menu.jsx --jsx=automatic --charset=utf8
text
import { jsx, jsxs } from "react/jsx-runtime";
const title = /* @__PURE__ */ jsx("h1", { className: "sarlavha", children: "Menyu" });
const item = /* @__PURE__ */ jsxs("li", { id: "osh", children: [
  "Osh: ",
  price,
  " so'm"
] });
const label = /* @__PURE__ */ jsx("label", { htmlFor: "ism", children: "Ismingiz" });
const off = /* @__PURE__ */ jsx("button", { disabled: true, children: "Tugadi" });
const card = /* @__PURE__ */ jsx(MenuCard, { name: "Osh", price });
const row = /* @__PURE__ */ jsx("li", { children: "Osh" }, "osh");
const list = /* @__PURE__ */ jsxs("ul", { children: [
  /* @__PURE__ */ jsx("li", { children: "Osh" }),
  /* @__PURE__ */ jsx("li", { children: "Manti" })
] });

Birinchi qator — automatic runtime ishi: transpiler jsx va jsxs funksiyalarini react/jsx-runtime modulidan o'zi import qildi. Shuning uchun faylingizda import React yozish shart emas (Transpilyatsiya darsidagi React is not defined voqeasini eslang). /* @__PURE__ */ — minifikator uchun belgi, u ham o'sha darsdan tanish.

2.2 Chiqishni o'qiymiz

Har JSX bitta funksiya chaqiruviga aylandi. Chaqiruvning qismlari:

JSX'da jsx() da Misol
teg nomi 1-argument "h1"
atributlar 2-argument — obyekt { className: "sarlavha" }
ichidagi narsa o'sha obyektda children children: "Menyu"
key 3-argument (alohida) jsx("li", {…}, "osh")

Shu obyektni React props (properties — "xususiyatlar") deb ataydi. Props'ni Props darsida batafsil o'rganamiz, bugun bitta gap yetadi: JSX'dagi har atribut — bitta obyekt kaliti.

Endi chiqishdagi mayda detallarga qaraymiz:

  • Kichik harfli teg — satr, katta harfli — o'zgaruvchi. <h1> → "h1" (qo'shtirnoq ichida), <MenuCard> → MenuCard (qo'shtirnoqsiz, o'zgaruvchi nomi). Transpiler katta harfga qarab hal qiladi. Komponent nomlari shuning uchun katta harf bilan boshlanadi (Komponentlar darsida).
  • price={price} → price. Kalit va qiymat nomi bir xil bo'lgani uchun esbuild obyektning qisqa yozuvini ishlatdi. Ma'nosi — price: price.
  • Qiymatsiz atribut — true. <button disabled> → disabled: true.
  • Bir nechta bola — massiv va jsxs. <li> ichida uch qism bor: "Osh: ", price, " so'm" — ular massivga yig'ildi. Oxiridagi s — "ko'plik" belgisi: jsxs React'ga "bu massiv qo'lda yozilgan, tartibi o'zgarmaydi" deydi. Nega bu muhim — ro'yxatlar va key darsida.
  • key — props'ga kirmaydi. U alohida, uchinchi argument bo'ldi. React uni o'zi uchun saqlaydi, komponentga bermaydi.

Maslahat: Saytimizdagi «Ishga tushir» tugmasi JSX'ni boshqa transpiler — sucrase bilan o'giradi. Uning chiqishi _jsxruntime.jsx.call(void 0, 'h1', {…}) ko'rinishida. Formati boshqa, lekin chaqirilayotgan funksiya o'sha — react/jsx-runtime dagi jsx. Vite 8 da esa Oxc ishlaydi. Qaysi vosita bo'lmasin, natija bir xil.

2.3 Element — oddiy obyekt

jsx() nima qaytaradi? Konsolga chiqarib ko'ramiz:

jsx
const title = <h1 className="sarlavha">Menyu</h1>;
console.log(title);
console.log(title.type, title.props);

Konsolda:

text
{$$typeof: Symbol(react.transitional.element), type: 'h1', key: null, props: {className: 'sarlavha', children: 'Menyu'}, _owner: null, _store: {}}
h1 {className: 'sarlavha', children: 'Menyu'}

Bu — React elementi (React element): "ekranda nima bo'lishi kerak" degan tavsif. Oddiy obyekt: type — teg nomi, props — atributlar va bolalar, key — kalit.

Ikki g'alati maydon:

  • $$typeof — React'ning "bu haqiqatan mening elementim" belgisi. Qiymati Symbol — uni JSON'da yozib bo'lmaydi. Nega bu xavfsizlik uchun muhim — keyingi darsda.
  • _owner va _store — development rejimidagi ichki maydonlar (ogohlantirishlar uchun). Ularga tegmaysiz.

Diqqat qiling: element — DOM tuguni emas. document.createElement("h1") haqiqiy tugun yaratadi, <h1> esa faqat uning tavsifini. O'xshatish: ofitsiant yozgan buyurtma qog'ozi — "1 osh, 2 non". Bu taomning o'zi emas, tavsifi. Oshpaz qog'ozni o'qib, haqiqiy taomni tayyorlaydi. React'da oshpaz — React DOM: u elementlarni o'qib, haqiqiy DOM tugunlarini yaratadi.

flowchart LR
  A["JSX yozuvi"] -->|"transpiler"| B["jsx() chaqiruvi"]
  B -->|"bajariladi"| C["React elementi<br/>(oddiy obyekt)"]
  C -->|"React DOM"| D["DOM tugunlari"]

Rasmda chapdan o'ngga qarang: birinchi o'q build paytida (Vite yoki saytdagi sucrase), qolganlari brauzerda bajariladi.

2.4 JSX'siz React

Agar JSX faqat qisqa yozuv bo'lsa, usiz ham ishlash kerak. Sinab ko'ramiz — jsx va jsxs ni o'zimiz import qilamiz:

jsx
import { jsx, jsxs } from "react/jsx-runtime";

function App() {
  return jsxs("ul", {
    children: [
      jsx("li", { children: "Osh — 35000 so'm" }),
      jsx("li", { children: "Manti — 30000 so'm" }),
    ],
  });
}

Ekranda:

text
Osh — 35000 so'm
Manti — 30000 so'm

Ishladi — bitta ham teg yozmadik. Real kodda bunday hech kim yozmaydi: react/jsx-runtime — transpiler uchun mo'ljallangan modul. Biz uni faqat isbot uchun chaqirdik: JSX — sintaksis, React'ning o'zi esa oddiy funksiyalar va obyektlar.

Maslahat: Eski kodda React.createElement("li", null, "Osh") ni ko'rasiz — bu classic runtime (Transpilyatsiya darsida). Farqi: bolalar children kaliti emas, qo'shimcha argumentlar bo'lib beriladi. Ma'nosi bir xil. React 19 da createElement hali bor, lekin JSX endi jsx() ga o'giriladi.

Tekshirib ko'ring: <Menu /> va <menu /> nimaga o'giriladi?

Javob

<Menu /> → jsx(Menu, {}) — Menu degan o'zgaruvchi (komponent). <menu /> → jsx("menu", {}) — satr, ya'ni HTML'dagi <menu> tegi. Transpiler faqat birinchi harfga qaraydi: katta harf — o'zgaruvchi, kichik harf — HTML teg.

3. Qoidalar JavaScript'dan kelib chiqadi

Endi Sardorning xatolariga qaytamiz. Har biri "JSX = jsx() chaqiruvi" degan bitta g'oyadan tushuntiriladi.

3.1 Bitta ildiz

Sardor sarlavha va matnni yonma-yon qaytarmoqchi bo'ldi:

jsx
function App() {
  return (
    <h1>Salom</h1>
    <p>Menyu</p>
  );
}

Saytda qizil quti:

text
JSX sintaksis xatosi (4-qator, 16-ustun): Unterminated regular expression

"Yopilmagan regular expression"? Qayerda regex bor? Buni JavaScript tahlilchisi (parser) kabi o'qib ko'ramiz. <h1>Salom</h1> — tugagan ifoda. Uning ortidan < keldi. Ifodadan keyingi < — JavaScript'da "kichik" operatori. Keyin p>Menyu<, so'ng /p> — / belgisi bilan regex boshlanadi, lekin yopuvchi / yo'q. Xabar g'alati, lekin mantiqli: tahlilchi JavaScript qoidasi bilan o'qiyapti. Qoida: xabar tushunarsiz bo'lsa, ko'rsatilgan joydan oldingi qatorni tekshiring.

Vite 8 (ichida Oxc) shu xatoni aniqroq aytadi:

text
Adjacent JSX elements must be wrapped in an enclosing tag.
Did you want a JSX fragment `<>...</>`?

"Yonma-yon JSX elementlari bitta o'rab turuvchi tegga olinishi kerak. JSX fragment <>...</> ni nazarda tutdingizmi?" Xuddi shu kod .tsx faylda bo'lsa, tsc ham to'xtaydi:

text
TS2657: JSX expressions must have one parent element.

"JSX ifodalarining bitta ota elementi bo'lishi shart." Nega? O'girilgan holatini tasavvur qiling: return jsx("h1", …) jsx("p", …);. Funksiya ikkita qiymat qaytara olmaydi — bu JavaScript qoidasi.

Tuzatish — ikkalasini bitta tegga o'rash:

jsx
function App() {
  return (
    <div>
      <h1>Salom</h1>
      <p>Menyu</p>
    </div>
  );
}

Ekranda:

text
Salom
Menyu

Ortiqcha <div> kerak bo'lmasa — <>…</> (Fragment) bor. U DOM'ga hech narsa qo'shmaydi; keyingi darsda to'liq ko'ramiz.

return dan keyingi qavslarga ham e'tibor bering. Ular JSX qoidasi emas — JavaScript'ning nuqta-vergulni avtomatik qo'yish (ASI) qoidasi uchun. Qavssiz return dan keyin yangi qatorga o'tsangiz, JavaScript return; deb o'qiydi va funksiya undefined qaytaradi:

jsx
function App() {
  return
    <h1>Menyu</h1>;
}

Ekran bo'sh qoladi, xato ham yo'q — eng yoqimsiz turdagi xato. Ko'p qatorli JSX'ni har doim return ( bilan boshlang.

3.2 Har teg yopiladi

HTML'da <img>, <br>, <input> yopilmaydi — ular bo'sh elementlar (void elements). JSX'da bunday istisno yo'q: har teg yopilishi shart. Aks holda tahlilchi tegning ichidagi narsani oxirigacha qidiradi:

jsx
function App() {
  return <img src="osh.jpg" alt="Osh">;
}

Saytda:

text
JSX sintaksis xatosi (2-qator, 40-ustun): Unterminated JSX contents

"Tugallanmagan JSX tarkibi" — tahlilchi <img> ning yopuvchi tegini fayl oxirigacha qidirdi va topmadi. .tsx faylda tsc bu safar uchta xato beradi:

text
TS17008: JSX element 'img' has no corresponding closing tag.
TS1381: Unexpected token. Did you mean `{'}'}` or `&rbrace;`?
TS1005: '</' expected.

Birinchisi — haqiqiy sabab: "img elementining yopuvchi tegi yo'q". Qolgan ikkitasi — oqibat: tahlilchi ; va } ni <img> ichidagi matn deb o'yladi. Qoida: bir nechta xato chiqsa, birinchisini tuzating — qolganlari ko'pincha o'zi yo'qoladi.

Tuzatish — o'zini yopuvchi teg (self-closing): <img src="osh.jpg" alt="Osh" />, <br />, <input />. Istalgan teg shunday yopilishi mumkin: ichi bo'sh <div></div> o'rniga <div />.

3.3 className va htmlFor

Sardorning ikkinchi xatosi:

jsx
function App() {
  return (
    <div class="karta">
      <label for="ism">Ism</label>
      <input id="ism" />
    </div>
  );
}

Konsolda:

text
Invalid DOM property `for`. Did you mean `htmlFor`?
Invalid DOM property `class`. Did you mean `className`?

Ekranda:

text
Ism

"Noto'g'ri DOM xususiyati for. htmlFor ni nazarda tutdingizmi?" Komponent chizildi, lekin React ogohlantirdi. (Konsoldagi xabarlar React'ning development rejimida chiqadi. Saytdagi «Ishga tushir» aynan shu rejimda ishlaydi.)

Nega className? JSX atributlari — props obyektining kalitlari. React DOM ularni HTML atribut nomi bilan emas, DOM xususiyati nomi bilan qabul qiladi. Atributlar va xususiyatlar darsidagi jadvalni eslang: class atributining xususiyati — el.className, for ning xususiyati — label.htmlFor. DOM API bu nomlarni tanlagan, chunki class va for JavaScript'ning kalit so'zlari. React o'sha nomlarga ergashdi. Vanilla kodda li.className = "taom" deb yozganingizni eslang — JSX'dagi className o'sha.

TypeScript bu yerda qattiqroq: ogohlantirish emas, xato.

tsx
export function App() {
  return (
    <div class="karta">
      <label for="ism">Ism</label>
      <input id="ism" />
    </div>
  );
}

Xato:

text
TS2322: Type '{ class: string; children: Element[]; }' is not assignable to type 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'.
  Property 'class' does not exist on type 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'. Did you mean 'className'?
TS2322: Type '{ for: string; children: string; }' is not assignable to type 'DetailedHTMLProps<LabelHTMLAttributes<HTMLLabelElement>, HTMLLabelElement>'.
  Property 'for' does not exist on type 'DetailedHTMLProps<LabelHTMLAttributes<HTMLLabelElement>, HTMLLabelElement>'. Did you mean 'htmlFor'?

Uzun, lekin o'qisa bo'ladi. { class: string; children: Element[]; } — TypeScript JSX atributlaridan yasagan props obyekti (yana isbot: atributlar — obyekt). DetailedHTMLProps<…> — <div> qabul qiladigan props turi, @types/react paketidan. Eng muhim qism — oxiri: Did you mean 'className'?.

3.4 camelCase atributlar

Xuddi shu qoida boshqa atributlarga ham tegishli: nom DOM xususiyatidan olinadi, ko'p so'zli nom esa camelCase (har keyingi so'z katta harf bilan) bo'ladi.

HTML JSX
tabindex tabIndex
maxlength, readonly maxLength, readOnly
onclick, oninput onClick, onInput
stroke-width (SVG) strokeWidth
aria-label, data-id o'zgarmaydi

Oxirgi qator — istisno: aria-* va data-* atributlari HTML'dagidek, chiziqcha bilan yoziladi.

Kichik harf bilan yozsangiz:

jsx
function App() {
  return (
    <div tabindex="0">
      <svg><circle r="5" stroke-width="2" /></svg>
      Osh
    </div>
  );
}

Konsolda:

text
Invalid DOM property `stroke-width`. Did you mean `strokeWidth`?
Invalid DOM property `tabindex`. Did you mean `tabIndex`?

Ekranda:

text
Osh

Hodisa atributlarida (onclick) xavf kattaroq: React kichik harfli onclick ni ishlovchi deb tanimaydi va bosilganda funksiya chaqirilmaydi. Hodisalarni Hodisalarni boshqarish darsida o'rganamiz; bugun faqat nomi. TypeScript buni ham ushlaydi:

tsx
export function App() {
  return <button onclick={() => {}}>Buyurtma</button>;
}

Xato:

text
TS2322: Type '{ onclick: () => void; children: string; }' is not assignable to type 'DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>'.
  Property 'onclick' does not exist on type 'DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>'. Did you mean 'onClick'?

3.5 style — obyekt

Sardorning uchinchi xatosi eng og'iri edi:

jsx
function App() {
  return <p style="color: green">Tayyor</p>;
}

Konsolda:

text
Uncaught Error: The `style` prop expects a mapping from style properties to values, not a string. For example, style={{marginRight: spacing + 'em'}} when using JSX.

"style props'i satr emas, stil xususiyatlaridan qiymatlarga xaritalash (obyekt) kutadi. Masalan: style={{marginRight: spacing + 'em'}}." Bu ogohlantirish emas — xato: komponent chizilmaydi, saytda «Komponentni chizishda xato» qutisi chiqadi.

To'g'risi — style={{ … }}. Ikki juft jingalak qavs boshida qo'rqitadi, lekin ularning vazifasi har xil: tashqi {} — "bu yerda JavaScript ifodasi" (pastda ko'ramiz), ichki {} — oddiy obyekt literali. Obyektni oldin o'zgaruvchiga olsangiz, ikkalasi ajralib ko'rinadi.

React DOM bu obyektdan qanday HTML yasashini ko'raylik:

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

const root = createRoot(document.getElementById("root"));
const box = { color: "green", fontSize: 18, padding: 8 };

flushSync(() => {
  root.render(
    <label htmlFor="ism" className="yorliq" style={box}>
      Ism
    </label>
  );
});
console.log(document.getElementById("root").innerHTML);

Konsolda:

text
<label for="ism" class="yorliq" style="color: green; font-size: 18px; padding: 8px;">Ism</label>

Ekranda:

text
Ism

flushSync — React'ga "hozir, shu zahoti chizib bo'l" degan buyruq. Usiz root.render ishni keyinroqqa qoldiradi va keyingi qatordagi innerHTML hali bo'sh bo'ladi. Uni bu yerda faqat natijani ko'rish uchun ishlatdik — oddiy kodda kerak bo'lmaydi.

Natijada uchta o'girish ko'rinyapti:

  • className → class, htmlFor → for: DOM'da yana oddiy HTML atributlari.
  • fontSize → font-size: kalitlar camelCase, xuddi stillarni JS'dan boshqarish darsidagi el.style.fontSize kabi.
  • 18 → 18px: son yozsangiz, React px qo'shadi. Birliksiz xususiyatlar (lineHeight, opacity, zIndex, flexGrow) bundan mustasno — ular son bo'lib qoladi. Boshqa birlik kerak bo'lsa — satr: width: "50%", padding: "1rem".

TypeScript satrni darhol rad etadi:

tsx
export function App() {
  return <p style="color: green">Tayyor</p>;
}

Xato:

text
TS2559: Type 'string' has no properties in common with type 'Properties<string | number, string & {}>'.

"string turining Properties<…> turi bilan umumiy xususiyati yo'q." Properties — CSS xususiyatlari obyekti turi (csstype paketidan, @types/react uni ishlatadi).

Maslahat: Amalda style kam ishlatiladi. Asosiy bezak — CSS fayl va className. style — hisoblanadigan qiymatlar uchun: progress chizig'ining kengligi, foydalanuvchi tanlagan rang. Uslub berish usullarini React'da stil berish darsida taqqoslaymiz.

Tekshirib ko'ring: style={{ marginTop: 10, lineHeight: 1.5 }} DOM'da qanday yoziladi?

Javob

style="margin-top: 10px; line-height: 1.5;". marginTop → margin-top (camelCase chiziqchaga qaytadi), 10 → 10px. lineHeight esa birliksiz xususiyat: 1.5 "shrift o'lchamining 1.5 baravari" degani, unga px qo'shilmaydi.

4. {} — JavaScript'ga eshik

4.1 Ifoda qo'yish

Shu paytgacha atribut qiymatlari qo'shtirnoqda edi — oddiy satr. Qiymat hisoblanishi kerak bo'lsa, jingalak qavs ishlatiladi. {} ichidagi kod JavaScript sifatida bajariladi:

jsx
function App() {
  const price = 35000;
  const isOpen = true;
  return (
    <div>
      <p>Narx: {price} so'm</p>
      <p>Ikki porsiya: {price * 2} so'm</p>
      <p>Holat: {isOpen ? "ochiq" : "yopiq"}</p>
      <p title={`Narx: ${price}`}>{"osh".toUpperCase()}</p>
    </div>
  );
}

Ekranda:

text
Narx: 35000 so'm
Ikki porsiya: 70000 so'm
Holat: ochiq
OSH

{} ikki joyda ishlaydi:

  • bola o'rnida — <p>{price}</p>: qiymat children ga tushadi;
  • atribut qiymati o'rnida — title={…}: qiymat props kalitiga tushadi.

Teg nomi o'rnida ishlamaydi: <{tag}> yozib bo'lmaydi.

Qo'shtirnoq va jingalak qavsni aralashtirmang. title="{price}" — oddiy satr, ichida jingalak qavslar bilan. esbuild chiqishida farq aniq ko'rinadi:

text
const d = /* @__PURE__ */ jsxs("p", { title: "{price}", children: [
  price,
  " so'm"
] });

Bu <p title="{price}">{price} so'm</p> ning o'girilgani. Atributda "{price}" satr bo'lib qoldi, bola o'rnidagi {price} esa o'zgaruvchi bo'ldi.

4.2 Nega {} ichida if yo'q

{} ichiga faqat ifoda (expression) yoziladi — qiymat beradigan kod: o'zgaruvchi, price * 2, funksiya chaqiruvi, ternary. if, for, const — ko'rsatmalar (statement): ular qiymat bermaydi.

jsx
function App() {
  const ok = true;
  return <p>{if (ok) { "ha" }}</p>;
}

Saytda:

text
JSX sintaksis xatosi (3-qator, 15-ustun): Unexpected token

O'girilgan holatini tasavvur qiling: jsx("p", { children: if (ok) … }). Obyekt kalitining qiymati o'rnida if turibdi — JavaScript bunga ruxsat bermaydi, xuddi const a = if (ok) … kabi. JSX qoidasi yana JavaScript qoidasidan chiqdi.

Ikki yo'l bor: ifoda variantini ishlatish ({ok ? "ha" : "yo'q"}) yoki if ni return dan oldin yozish:

jsx
function App() {
  const ok = true;
  let answer = "yo'q";
  if (ok) {
    answer = "ha";
  }
  return <p>Javob: {answer}</p>;
}

Ekranda:

text
Javob: ha

Shartga qarab UI tanlashning hamma usullari — Shartli render darsida. {} ichiga qanday qiymat qo'ysangiz ekranda nima chiqishi — keyingi darsda.

Tekshirib ko'ring: HTML'dagi <label for="tel">Telefon</label> ni JSX'ga o'giring: <label [:htmlFor] ="tel">Telefon</label>. <input maxlength="9"> esa: <input [:maxLength] ="9" />.

Javob

htmlFor va maxLength. Ikkalasi ham DOM xususiyati nomi: label.htmlFor, input.maxLength. Ikkinchisida tegni /> bilan yopishni unutmang.

5. HTML → JSX: yig'ma jadval

HTML JSX Sabab
<img src="a.jpg"> <img src="a.jpg" /> har teg yopiladi
class="karta" className="karta" DOM xususiyati nomi
for="ism" htmlFor="ism" DOM xususiyati nomi
tabindex="0" tabIndex={0} camelCase
style="color: red" style={{ color: "red" }} style — obyekt
<!-- izoh --> {/* izoh */} keyingi darsda
ikki ildiz yonma-yon <div> yoki <> ichida funksiya bitta qiymat qaytaradi

tabIndex={0} ga e'tibor bering: "0" satr ham ishlaydi, lekin son {} bilan yoziladi. Qoida: satr — qo'shtirnoqda, boshqa hamma narsa (son, boolean, o'zgaruvchi, obyekt, funksiya) — {} da.

6. Ko'p uchraydigan xatolar

6.1 Ko'chirilgan qatorlardagi matn yopishib qoladi

jsx
function App() {
  return (
    <p>
      Narxi:
      <b>35000</b>
      so'm
    </p>
  );
}

Ekranda:

text
Narxi:35000so'm

Bo'shliqlar qayerga ketdi? JSX'ning qoidasi: qator ko'chishi bor bo'shliq butunlay olib tashlanadi. esbuild chiqishida ko'rinadi — children: ["Narxi:", jsx("b", …), "so'm"], bo'sh joy yo'q. Bu HTML'dan farq qiladi: HTML'da qator ko'chishi bitta bo'shliqqa aylanadi.

Tuzatish — so'zlarni bitta qatorda yozing (Narxi: <b>35000</b> so'm) yoki bo'shliqni ifoda sifatida qo'ying: {" "}.

jsx
function App() {
  return (
    <p>
      Narxi: <b>35000</b> so'm
    </p>
  );
}

Ekranda:

text
Narxi: 35000 so'm

6.2 Komponent nomi kichik harf bilan

jsx
function menuCard() {
  return <p>Osh</p>;
}

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

Konsolda:

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

Ekran bo'sh: <menuCard /> → jsx("menuCard", {}) — satr, ya'ni React menucard degan noma'lum HTML teg yaratdi. Funksiya umuman chaqirilmadi. Xabar: "Komponent nomi katta harf bilan (PascalCase) bo'lsin". Nom MenuCard bo'lsa, hammasi joyida.

6.3 Qisqa jadval

Belgi Sabab Davosi
Unterminated regular expression yonma-yon ikki ildiz <div> yoki <> bilan o'rang
Unterminated JSX contents <img>, <br> yopilmagan <img />
Invalid DOM property 'class' HTML nomi className, htmlFor
style prop expects a mapping style satr style={{ … }}
ekran bo'sh, xato yo'q return dan keyin qator ko'chdi return (
Unexpected token {} ichida if/for ko'rsatma ternary yoki return dan oldin

7. Mashqlar

Mashqlar kurs/mashqlar/17/03-jsx/ da. Yechimni «Ishga tushir» bilan sinang yoki o'z React loyihangizdagi App o'rniga qo'yib ko'ring.

1-mashq (oson): HTML'ni JSX'ga o'giring

«Bahor» saytidagi buyurtma kartasining HTML'i bor. Uni App komponentiga JSX qilib ko'chiring. Ekran va konsol toza bo'lsin (ogohlantirishsiz).

html
<div class="karta" tabindex="0">
  <img src="osh.jpg" alt="Osh">
  <label for="soni">Soni:</label>
  <input id="soni" type="number" value="1" readonly>
  <p style="color: green; font-weight: bold">Tayyor</p>
  <br>
</div>

Ishora: jadvaldagi har qatorni tekshiring — yopilmagan teglar ikkita emas, uchta. style dagi font-weight qanday yoziladi?

Yechim
jsx
function App() {
  return (
    <div className="karta" tabIndex={0}>
      <img src="osh.jpg" alt="Osh" />
      <label htmlFor="soni">Soni:</label>
      <input id="soni" type="number" value="1" readOnly />
      <p style={{ color: "green", fontWeight: "bold" }}>Tayyor</p>
      <br />
    </div>
  );
}

Ekranda:

text
Soni:
Tayyor

Yopilmagan teglar — <img>, <input>, <br>. readonly → readOnly va qiymatsiz qoldi (true). font-weight → fontWeight. readOnly ni unutsangiz, React boshqa ogohlantirish beradi: value bor, lekin o'zgartirish yo'li yo'q. Bu mavzu — Formalar darsida.

2-mashq (o'rta): JSX'siz yozing

Quyidagi komponentni JSX ishlatmasdan, react/jsx-runtime dagi jsx va jsxs bilan qayta yozing. Ekrandagi natija bir xil bo'lsin.

jsx
function App() {
  return (
    <section className="menyu">
      <h2>Bugungi taomlar</h2>
      <p>Osh — <b>35000</b> so'm</p>
    </section>
  );
}

Ekranda:

text
Bugungi taomlar
Osh — 35000 so'm

Ishora: «Chiqishni o'qiymiz» bo'limidagi qoidalar — bitta bola → jsx va children da qiymat; bir nechta bola → jsxs va massiv. <p> ichida nechta bola bor? Matnlardagi bo'shliqlarni yo'qotmang.

Yechim
jsx
import { jsx, jsxs } from "react/jsx-runtime";

function App() {
  return jsxs("section", {
    className: "menyu",
    children: [
      jsx("h2", { children: "Bugungi taomlar" }),
      jsxs("p", {
        children: [
          "Osh — ",
          jsx("b", { children: "35000" }),
          " so'm",
        ],
      }),
    ],
  });
}

Ekranda:

text
Bugungi taomlar
Osh — 35000 so'm

<section> ning ikkita bolasi bor (h2 va p) — jsxs. <p> ning uchta: "Osh — ", <b> elementi va " so'm" — yana jsxs. <h2> va <b> ning bittadan bolasi bor — jsx. Bo'shliqlar satrlarning ichida: "Osh — " oxirida, " so'm" boshida. JSX bitta qatorda yozilgani uchun ular saqlangan edi.

3-mashq (qiyin): Transpiler bo'lib ko'ring

Quyidagi JSX esbuild'dan qanday chiqishini qog'ozda yozing. Keyin Row.jsx fayliga saqlab, npx esbuild@0.28.2 Row.jsx --jsx=automatic --charset=utf8 bilan solishtiring.

jsx
const row = (
  <li key={dish.id} className={dish.hot ? "issiq" : ""}>
    <DishName text={dish.name} />
    {dish.price} so'm
  </li>
);

Uchta savolga ham javob bering: (1) jsx mi yoki jsxs? (2) key qayerga tushadi? (3) DishName qo'shtirnoqdami?

Yechim
text
import { jsx, jsxs } from "react/jsx-runtime";
const row = /* @__PURE__ */ jsxs("li", { className: dish.hot ? "issiq" : "", children: [
  /* @__PURE__ */ jsx(DishName, { text: dish.name }),
  dish.price,
  " so'm"
] }, dish.id);
  1. <li> ning uchta bolasi bor (DishName elementi, dish.price, " so'm") — jsxs. DishName ning bolasi yo'q — jsx.
  2. key — props'da emas, oxirgi argumentda: }, dish.id).
  3. Yo'q: DishName katta harf bilan — o'zgaruvchi. "li" esa satr.

Yana ikki detal: ternary {} dan olinib, to'g'ridan-to'g'ri className qiymatiga qo'yildi. {dish.price} va so'm orasidagi bo'shliq satrning boshida saqlandi (" so'm") — ular bitta qatorda edi. Qator ko'chishi esa izsiz yo'qoldi.

8. Real ishda

  • HTML maketni JSX'ga o'girish — frontend dasturchining kundalik ishi. Dizayner yoki eski sahifadan kelgan HTML'da class, for, style="…" va yopilmagan teglar albatta bo'ladi. TypeScript (.tsx) ularning hammasini build'dan oldin ushlaydi — vazifalar da tsc -b aynan shuning uchun.
  • JSX faqat React'niki emas. Preact ham JSX ishlatadi — faqat jsx() boshqa paketdan keladi (tsconfig'dagi jsxImportSource sozlamasi). G'oya o'sha: JSX — funksiya chaqiruvining qisqa yozuvi.
  • Intervyu savollari: "JSX nima va brauzer uni qanday tushunadi?", "Nega class emas, className?", "React.createElement va jsx() farqi?", "Nega komponent bitta ildiz qaytaradi?", "React elementi va DOM tuguni farqi?".

Xulosa

  • JSX — sintaksis: transpiler uni jsx("teg", props, key) yoki jsxs(…) chaqiruviga aylantiradi, import'ni automatic runtime o'zi qo'shadi.
  • jsx() natijasi — React elementi: type, props, key li oddiy obyekt. DOM tugunini React DOM yaratadi.
  • Bitta ildiz — funksiya bitta qiymat qaytaradi; har teg yopiladi; ko'p qatorli JSX — return ( bilan.
  • Atributlar — props kalitlari: className, htmlFor, camelCase (tabIndex, onClick); aria-*, data-* o'zgarmaydi.
  • style — obyekt: style={{ fontSize: 18 }} → font-size: 18px.
  • {} ichida faqat ifoda: o'zgaruvchi, hisob, chaqiruv, ternary — if emas.

Keyingi dars: JSX II: ifodalar, Fragment va nima ekranga chiqadi — {} ichiga son, massiv, null yoki obyekt qo'ysak nima bo'ladi, 0 && tuzog'i va JSX nega XSS'dan himoya qiladi.

Manbalar

  • React: "Writing Markup with JSX", "JavaScript in JSX with Curly Braces" — react.dev/learn
  • React: "Common components (e.g. <div>)" — className, htmlFor, style — react.dev/reference/react-dom/components/common
  • React blog: "Introducing the New JSX Transform" (2020-09-22) — legacy.reactjs.org/blog
  • esbuild: "JSX" (--jsx=automatic) — esbuild.github.io/api
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
JSX I: JSX aslida JavaScript — jsx() chaqiruvi va yozish qoidalari — IlmHamroh