Mundarija (33)
- Bu darsda
- 1. Nega bu kerak?
- 2. {} ichidagi ifodalar
- 2.1 Qisqa takror
- 2.2 Element ham qiymat
- 3. Nima ekranga chiqadi
- 3.1 Har tur bitta qatorda
- 4. 0 && tuzog'i
- 4.1 Tuzoqni jonli ko'ramiz
- 4.2 NaN — o'sha tuzoq, qo'shimcha ogohlantirish bilan
- 4.3 TypeScript ham ushlamaydi
- 4.4 Uch tuzatish
- 5. Obyekt chizilmaydi
- 5.1 Objects are not valid as a React child
- 5.2 Funksiya — ogohlantirish
- 5.3 TypeScript ikkalasini ham ushlaydi
- 6. Massivni chizish
- 7. Fragment
- 7.1 Ortiqcha <div> siz guruhlash
- 7.2 Ro'yxatda Fragment: key kerak
- 8. JSX ichida izoh
- 9. JSX va XSS
- 9.1 Satr — har doim matn
- 9.2 $$typeof — soxta elementdan himoya
- Hujumchi nigohi
- 10. Ko'p uchraydigan xatolar
- 11. Mashqlar
- 1-mashq (oson): Ekranda nima chiqadi?
- 2-mashq (o'rta): Sardorning uchta xatosi
- 3-mashq (qiyin): Har qiymatni xavfsiz ko'rsatadigan yordamchi
- 12. Real ishda
- Xulosa
- Manbalar
JSX II: ifodalar, Fragment va nima ekranga chiqadi — 0 && tuzog'i va XSS himoyasi
Qisqacha: JSX'dagi
{}ichiga istalgan ifoda yoziladi, lekin har qiymat turi ekranda o'zicha chiqadi. Satr va son — matn bo'lib;null,undefined,truevafalse— umuman ko'rinmaydi; massiv — elementlari ketma-ket.0vaNaNesa ko'rinadi — shuning uchun{count && <b>…</b>}bo'sh savatda0chiqaradi. Oddiy obyekt chizilmaydi, React xato tashlaydi. Ortiqcha teg qo'shmasdan guruhlash uchun —<>…</>(Fragment), ro'yxatda esa<Fragment key={…}>. JSX satrlarni har doim matn sifatida qo'yadi, shuning uchuninnerHTMLdagi XSS bu yerda ishlamaydi.
Bu darsda
{}ga qo'yilgan qiymat ekranda qanday chiqishini oldindan ayta olasiz: satr, son, boolean,null, massiv, obyekt.0 &&vaNaN &&tuzog'ini taniysiz va uch xil yo'l bilan tuzatasiz.<>…</>va<Fragment key>ni qachon ishlatishni bilasiz.- JSX ichiga to'g'ri izoh yozasiz.
- JSX nega XSS'dan himoya qilishini va qayerda himoya tugashini tushuntira olasiz.
Oldin bilishingiz kerak: JSX I: JSX aslida JavaScript, Mantiqiy operatorlar va qisqa tutashuv, Kontentni o'zgartirish va XSS xavfi.
1. Nega bu kerak?
Oldingi darsda JSX jsx() chaqiruviga aylanishini, {} esa JavaScript'ga eshik ekanini ko'rdik. Endi savol: eshikdan nima kirsa, ekranda nima chiqadi?
Sardor «Bahor» saytiga savat yozdi: savatda taom bo'lsa, "3 ta taom" yozuvi chiqsin. Kod qisqa va chiroyli edi: {count && <b>{count} ta taom</b>}. Ertasiga Jasur aka telefon qildi: "Savat bo'sh bo'lsa, ekranda nega yolg'iz 0 turibdi?"
Vanilla JavaScript'da qoida bitta edi: textContent = qiymat — qiymat satrga aylanadi va chiqadi. React'da har tur o'z qoidasiga ega. Ba'zi qiymatlar yashirinadi, ba'zilari ko'rinib qoladi, ba'zilari butun komponentni yiqitadi. Bugun shu jadvalni to'liq yig'amiz.
Hayotiy o'xshatish: kassadagi chek printeri. Unga taom nomi bersangiz — chop etadi. Son bersangiz — chop etadi. "Hech narsa" belgisini bersangiz — qatorni o'tkazib yuboradi. Butun qog'oz papkani tiqsangiz — to'xtab, xato beradi. React'ning {} i ham shunday printer.
2. {} ichidagi ifodalar
2.1 Qisqa takror
{} ichiga faqat ifoda yoziladi — qiymat beradigan kod (JSX I darsida if nega sig'masligini ko'rdik). JavaScript'dan bilgan ifodalaringizning hammasi ishlaydi: o'zgaruvchi, arifmetika, funksiya chaqiruvi, ternary, &&, || va ??.
function App() {
const note = null;
const name = "";
return (
<div>
<p>Izoh: {note ?? "yo'q"}</p>
<p>Mehmon: {name || "nomsiz"}</p>
<p>{name.length > 0 ? name : "Ism kiritilmagan"}</p>
</div>
);
}Ekranda:
Izoh: yo'q
Mehmon: nomsiz
Ism kiritilmagan?? faqat null va undefined da zaxira qiymatni oladi, || esa har qanday falsy qiymatda — bo'sh satrda ham (?? va ?. darsida). JSX bu yerda hech narsa o'zgartirmaydi: avval JavaScript ifodani hisoblaydi, keyin React natijani chizadi.
2.2 Element ham qiymat
<b>Yangi</b> — oddiy obyekt (oldingi darsda konsolda ko'rdik). Demak uni o'zgaruvchiga saqlash, funksiyadan qaytarish yoki massivga qo'yish mumkin:
function App() {
const isNew = true;
const badge = <b>Yangi!</b>;
return (
<p>
Manti {isNew ? badge : null}
</p>
);
}Ekranda:
Manti Yangi!null — "bu yerda hech narsa chizma" degani. Nega aynan shunday — keyingi bo'limda.
3. Nima ekranga chiqadi
3.1 Har tur bitta qatorda
Hamma turni bitta ro'yxatda sinaymiz:
function App() {
return (
<ul>
<li>satr: {"Osh"}</li>
<li>son: {35000}</li>
<li>true: {true}</li>
<li>false: {false}</li>
<li>null: {null}</li>
<li>undefined: {undefined}</li>
<li>nol: {0}</li>
<li>NaN: {NaN}</li>
<li>bo'sh satr: [{""}]</li>
<li>massiv: {["Osh", "Manti", 3]}</li>
</ul>
);
}Ekranda:
satr: Osh
son: 35000
true:
false:
null:
undefined:
nol: 0
NaN: NaN
bo'sh satr: []
massiv: OshManti3Natijani jadvalga yig'amiz:
| Qiymat | Ekranda | Izoh |
|---|---|---|
"Osh", 35000 |
matn | odatdagidek |
true, false |
hech narsa | && uchun ataylab |
null, undefined |
hech narsa | "chizma" belgisi |
0, NaN |
0, NaN |
son — ko'rinadi! |
"" |
hech narsa | bo'sh matn |
| massiv | elementlari ketma-ket | ajratuvchisiz |
| oddiy obyekt | xato | pastda |
Uch narsaga e'tibor bering.
Boolean ko'rinmaydi. {true} ekranga "true" yozmaydi. Bu ataylab qilingan: shunda {isOpen && <p>Ochiq</p>} yozish mumkin. isOpen false bo'lsa, ifoda false ga teng va React uni o'tkazib yuboradi.
Son har doim ko'rinadi. 0 ham son, NaN ham. React sonni "hech narsa" deb hisoblamaydi — ehtimol siz aynan nolni ko'rsatmoqchisiz ("Savatda: 0 ta").
Massiv elementlari yopishadi. ["Osh", "Manti", 3] → OshManti3. React massivni vergul bilan ulamaydi — har elementni alohida bola sifatida chizadi. Vergul yoki ro'yxat kerak bo'lsa — o'zingiz yasaysiz: .join(", ") yoki .map() bilan <li> lar (pastda).
Maslahat: React 19 da
BigIntham son kabi chiqadi:{10n}→10.{-0}esa0bo'lib chiqadi.
Tekshirib ko'ring:
<p>{"0"}</p>va<p>{0}</p>farqi bormi?<p>{[]}</p>nima chiqaradi?
Javob
Ekranda farq yo'q — ikkalasi ham 0. Lekin sabab boshqa: "0" — satr, 0 — son, ikkalasi ham matn bo'lib chiqadi. Farq && bilan paydo bo'ladi: "0" truthy (bo'sh bo'lmagan satr), 0 esa falsy. {[]} — bo'sh massiv, chizadigan elementi yo'q — ekranda hech narsa.
4. 0 && tuzog'i
4.1 Tuzoqni jonli ko'ramiz
Avval JavaScript'ni eslaymiz (Mantiqiy operatorlar darsi). a && b true/false qaytarmaydi. a falsy bo'lsa — a ning o'zini qaytaradi, aks holda b ni. Demak 0 && "ko'p" → 0, false && "ko'p" → false.
Endi Sardorning savati. Quyidagi misolda ikkita tugma bor. onClick — bosilganda chaqiriladigan funksiya (Hodisalarni boshqarish darsida to'liq). draw() esa Birinchi React loyiha darsidagi root.render ni yangi count bilan qayta chaqiradi. Bu vanilla uslubi; React'ning o'z xotirasi — state — useState darsida.
import { createRoot } from "react-dom/client";
const root = createRoot(document.getElementById("root"));
let count = 0;
function draw() {
root.render(
<div>
<p>Savat: {count && <b>{count} ta taom</b>}</p>
<button onClick={() => { count++; draw(); }}>+1</button>{" "}
<button onClick={() => { count = 0; draw(); }}>Tozalash</button>
</div>
);
}
draw();Ekranda:
Savat: 0
+1 Tozalash«Ishga tushir» ni bosing va tugmalarni sinang. Har bosishda nima bo'lishi:
| Qadam | count |
count && … |
Ekranda |
|---|---|---|---|
| boshida | 0 |
0 |
Savat: 0 |
| «+1» | 1 |
<b> elementi |
Savat: 1 ta taom |
| «Tozalash» | 0 |
0 |
Savat: 0 |
Jasur aka ko'rgan yolg'iz 0 — aynan shu. JavaScript 0 qaytardi, React esa sonni chizdi.
4.2 NaN — o'sha tuzoq, qo'shimcha ogohlantirish bilan
Reyting hali hisoblanmagan bo'lsa, NaN bo'lishi mumkin (masalan 0 / 0):
function App() {
const rating = NaN;
return <p>{rating && <b>{rating} yulduz</b>}</p>;
}Konsolda:
Received NaN for the `children` attribute. If this is expected, cast the value to a string.Ekranda:
NaN"children uchun NaN keldi. Agar bu kutilgan bo'lsa, qiymatni satrga aylantiring." React NaN ni chizdi, lekin bu deyarli har doim xato ekanini sezib, ogohlantirdi.
4.3 TypeScript ham ushlamaydi
export function App() {
const count: number = 0;
return <p>Savat: {count && <b>{count} ta taom</b>}</p>;
}Ekranda:
Savat: 0Tip xatosi yo'q: 0 — son, son esa {} ga qo'yish mumkin bo'lgan qiymat. TypeScript'dan bu yerda yordam kutmang — tuzoq mantiqda, turda emas.
4.4 Uch tuzatish
&& ning chap tomoni haqiqiy boolean bo'lsin:
- taqqoslash:
{count > 0 && <b>…</b>}— eng aniq; - ikki inkor:
{!!count && <b>…</b>}yoki{Boolean(count) && …}; - ternary:
{count > 0 ? <b>…</b> : "bo'sh"}— bo'sh holatga ham matn kerak bo'lsa.
Ternary bilan tuzatilgan savat. Bu safar blok tugmalarni o'zi bosadi: avval «+1», keyin «Tozalash».
import { createRoot } from "react-dom/client";
const root = createRoot(document.getElementById("root"));
let count = 0;
function draw() {
root.render(
<div>
<p>Savat: {count > 0 ? <b>{count} ta taom</b> : "bo'sh"}</p>
<button onClick={() => { count++; draw(); }}>+1</button>{" "}
<button onClick={() => { count = 0; draw(); }}>Tozalash</button>
</div>
);
}
draw();Ekranda:
Savat: bo'sh
+1 TozalashKo'pincha tuzoq .length bilan uchraydi: {orders.length && <List />}. Ro'yxat bo'sh bo'lsa — 0. Qoida bitta: && chapida son turgan bo'lsa, uni > 0 bilan taqqoslang. Shartli chizishning hamma usullari — Shartli render darsida.
5. Obyekt chizilmaydi
5.1 Objects are not valid as a React child
Sardor buyurtmani to'liq chiqarmoqchi bo'ldi:
function App() {
const order = { dish: "Osh", price: 35000 };
return <p>{order}</p>;
}Konsolda:
Uncaught Error: Objects are not valid as a React child (found: object with keys {dish, price}). If you meant to render a collection of children, use an array instead."Obyektlar React bolasi bo'la olmaydi (topildi: dish, price kalitli obyekt). Bolalar to'plamini chizmoqchi bo'lsangiz, massiv ishlating." Saytda «Komponentni chizishda xato» qutisi chiqadi, ostida Maslahat va Komponentlar: App → p — xato qaysi komponent ichida ekani.
Nega React taxmin qilmaydi? Obyektni qanday ko'rsatish kerak — {"dish":"Osh"} mi, "Osh, 35000" mi, jadvalmi? Bunga faqat siz javob bera olasiz. Shuning uchun React jim qolmaydi, to'xtaydi. Tuzatish — kerakli maydonlarni o'zingiz tanlang: <p>{order.dish} — {order.price} so'm</p>.
Date ham obyekt: {new Date()} xuddi shu xatoni beradi (found: [object Date]). Sanani satrga aylantirib qo'ying.
5.2 Funksiya — ogohlantirish
Qavslarni unutish — boshqa ko'p uchraydigan xato:
function getPrice() {
return 35000;
}
function App() {
return <p>Narx: {getPrice} so'm</p>;
}Konsolda:
Functions are not valid as a React child. This may happen if you return getPrice instead of <getPrice /> from render. Or maybe you meant to call this function rather than return it.
<p>{getPrice}</p>Ekranda:
Narx: so'm"Funksiyalar React bolasi bo'la olmaydi. … Balki bu funksiyani qaytarish o'rniga chaqirmoqchi edingiz?" Bu safar xato emas, ogohlantirish: funksiya o'rni bo'sh qoldi. Ikkinchi qator — xato aynan qayerda ekanini ko'rsatadi. Tuzatish — {getPrice()}.
5.3 TypeScript ikkalasini ham ushlaydi
function getPrice(): number {
return 35000;
}
export function App() {
const order = { dish: "Osh", price: 35000 };
return (
<p>
{order} {getPrice}
</p>
);
}Xato:
TS2322: Type '{ dish: string; price: number; }' is not assignable to type 'ReactNode'.
TS2322: Type '() => number' is not assignable to type 'ReactNode'.ReactNode — {} ga qo'yish mumkin bo'lgan hamma qiymatlarning turi (@types/react dan). Unga kiradi: satr, son, bigint, boolean, null, undefined, element va shularning massivi. Oddiy obyekt ham, funksiya ham unda yo'q. Bu turni Props va children darslarida ko'p uchratasiz. 0 && tuzog'idan farqli, bu yerda TypeScript haqiqatan yordam beradi.
6. Massivni chizish
Massiv elementlari ketma-ket chiziladi — demak elementlar massivini ham chizsa bo'ladi. Ro'yxat odatda .map() bilan yasaladi:
const menu = [
{ id: 1, name: "Osh", price: 35000 },
{ id: 2, name: "Manti", price: 30000 },
];
function App() {
return (
<ul>
{menu.map((dish) => (
<li key={dish.id}>{dish.name} — {dish.price} so'm</li>
))}
</ul>
);
}Ekranda:
Osh — 35000 so'm
Manti — 30000 so'mHar obyekt <li> elementiga aylandi — obyekt emas, element massivi chizilyapti, xato yo'q. Yangi atribut key={dish.id} — React'ga har qatorni tanib olish uchun yorliq. JSX I darsida jsxs "qo'lda yozilgan, o'zgarmas massiv" ekanini aytgan edik. Map natijasi esa o'zgaruvchan — undagi har element key so'raydi. Kalitni unutsangiz:
function App() {
const dishes = ["Osh", "Manti", "Lag'mon"];
return <ul>{dishes.map((d) => <li>{d}</li>)}</ul>;
}Konsolda:
Each child in a list should have a unique "key" prop.
Check the render method of `App`. See https://react.dev/link/warning-keys for more information.Ekranda:
Osh
Manti
Lag'mon"Ro'yxatdagi har bolada noyob key props'i bo'lishi kerak." Ekran to'g'ri, lekin ogohlantirish bejiz emas. key qoidalari va indeksni key qilishning xavfi — Ro'yxatlar va key darsida.
7. Fragment
7.1 Ortiqcha <div> siz guruhlash
JSX I darsida bitta ildiz qoidasini <div> bilan yechdik. Lekin ba'zan <div> HTML'ni buzadi:
<ul>ichida faqat<li>bo'lishi kerak;- jadval qatori
<tr>ichida faqat<td>yoki<th>; <dl>ichida<dt>va<dd>juftliklari;- Flexbox yoki Grid'da ortiqcha
<div>bolalarning joylashuvini o'zgartiradi.
Fragment — "ko'rinmas o'ram": elementlarni guruhlaydi, lekin DOM'ga hech narsa qo'shmaydi. Qisqa yozuvi — <>…</>:
import { flushSync } from "react-dom";
import { createRoot } from "react-dom/client";
const root = createRoot(document.getElementById("root"));
flushSync(() => {
root.render(
<>
<h1>Menyu</h1>
<p>Bugun 4 ta taom</p>
</>
);
});
console.log(document.getElementById("root").innerHTML);Konsolda:
<h1>Menyu</h1><p>Bugun 4 ta taom</p>Ekranda:
Menyu
Bugun 4 ta taom#root ichida o'ram yo'q — h1 va p to'g'ridan-to'g'ri. (flushSync — oldingi darsdagidek, natijani darhol ko'rish uchun.) esbuild'da <> nimaga aylanishi:
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
const page = /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx("h1", { children: "Menyu" }),
/* @__PURE__ */ jsx("p", { children: "Bugun 4 ta taom" })
] });<> — maxsus Fragment komponenti uchun qisqa yozuv. React uni ko'rib, faqat bolalarini chizadi.
7.2 Ro'yxatda Fragment: key kerak
Menyuni <dl> da ko'rsatamiz: har taomga ikkita element — <dt> (nomi) va <dd> (narxi). .map() har safar ikkita element qaytarishi kerak — demak Fragment:
const menu = [
{ id: 1, name: "Osh", price: 35000 },
{ id: 2, name: "Manti", price: 30000 },
];
function App() {
return (
<dl>
{menu.map((m) => (
<>
<dt>{m.name}</dt>
<dd>{m.price} so'm</dd>
</>
))}
</dl>
);
}Konsolda:
Each child in a list should have a unique "key" prop.
Check the render method of `App`. See https://react.dev/link/warning-keys for more information.Ekranda:
Osh
35000 so'm
Manti
30000 so'mRo'yxat elementi endi Fragment — key unga kerak. Qisqa yozuvga atribut yozib bo'lmaydi:
function App() {
const menu = [{ id: 1, name: "Osh" }];
return (
<dl>
{menu.map((m) => (
<key={m.id}>
<dt>{m.name}</dt>
</>
))}
</dl>
);
}Saytda:
JSX sintaksis xatosi (5-qator, 22-ustun): Unexpected token, expected ","<key= ni tahlilchi teg deb o'qimadi — <> dan boshqa narsani bilmaydi. Yechim — to'liq yozuv: Fragment ni react dan import qilib, key bering:
import { Fragment } from "react";
const menu = [
{ id: 1, name: "Osh", price: 35000 },
{ id: 2, name: "Manti", price: 30000 },
];
function App() {
return (
<dl>
{menu.map((m) => (
<Fragment key={m.id}>
<dt>{m.name}</dt>
<dd>{m.price} so'm</dd>
</Fragment>
))}
</dl>
);
}Ekranda:
Osh
35000 so'm
Manti
30000 so'mOgohlantirish yo'qoldi. Fragment boshqa atributlarni qabul qilmaydi: <Fragment className="menyu"> yozsangiz, React aytadi: React.Fragment can only have `key`, `ref`, and `children` props — "Fragment faqat key, ref va children qabul qiladi". Fragment DOM'da yo'q — className qo'yadigan joy ham yo'q. Eski kodda <React.Fragment key={…}> ni ko'rasiz — o'sha narsa, React obyekti orqali.
Tekshirib ko'ring: Qaysi holatda
<>yetadi, qaysi birida<Fragment key>kerak? (a) komponent<h1>va<p>qaytaradi; (b).map()har taomga<dt>va<dd>qaytaradi; (c).map()har taomga bitta<li>qaytaradi.
Javob
(a) <> — ro'yxat emas, key kerak emas. (b) <Fragment key={m.id}> — ro'yxat elementi Fragment, key unga beriladi. (c) Fragment umuman kerak emas — <li key={…}> ning o'zi bitta ildiz.
8. JSX ichida izoh
HTML izohi <!-- --> JSX'da ishlamaydi:
function App() {
return (
<div>
<!-- narxlar -->
<p>Menyu</p>
</div>
);
}Saytda:
JSX sintaksis xatosi (4-qator, 9-ustun): Unexpected tokenJSX ichida izoh — JavaScript izohi, {} ichida:
function App() {
return (
<p /* teg ichida ham bo'ladi */ className="narx">
{/* ko'p qatorli
izoh */}
Osh
{
// bir qatorli izoh
}
</p>
);
}Ekranda:
Osh{/* … */} — eng ko'p ishlatiladigan shakl. Nega {} kerak? Teglar orasidagi hamma narsa — matn. /* izoh */ ni qavssiz yozsangiz, u ekranga matn bo'lib chiqadi. {} ichida esa JavaScript: izohdan keyin ifoda yo'q — bo'sh {} hech narsa chizmaydi. // izohdan keyin } alohida qatorda bo'lishi shart. Aks holda } ham izohga kirib ketadi va tahlilchi Unterminated JSX contents deydi.
9. JSX va XSS
9.1 Satr — har doim matn
Kontentni o'zgartirish va XSS xavfi darsida mehmon izohiga <img src="x" onerror="…"> yozilgan edi. innerHTML uni teg deb o'qidi va kod ishga tushdi:
// ❌ vanilla: satr HTML deb o'qiladi
izoh.innerHTML = comment;Xuddi shu satrni JSX'ga beramiz:
import { flushSync } from "react-dom";
import { createRoot } from "react-dom/client";
const comment = '<img src="x" onerror="console.log(\'XSS\')">Zo\'r';
const root = createRoot(document.getElementById("root"));
flushSync(() => root.render(<p>Izoh: {comment}</p>));
console.log(document.getElementById("root").innerHTML);Konsolda:
<p>Izoh: <img src="x" onerror="console.log('XSS')">Zo'r</p>Ekranda:
Izoh: <img src="x" onerror="console.log('XSS')">Zo'r< va > < va > ga aylandi: brauzer ularni teg emas, harf deb ko'rsatdi. Mehmon izohni teg belgilari bilan birga ko'radi — hech qanday kod ishlamadi. Sabab: React DOM satrni matn tuguni sifatida qo'yadi, xuddi textContent kabi. {} dagi satr HTML bo'lib o'qilmaydi — hech qachon.
9.2 $$typeof — soxta elementdan himoya
JSX I darsida elementda $$typeof: Symbol(react.transitional.element) borligini ko'rdik. Endi uning foydasi. Server JSON qaytardi, unda element "shaklidagi" obyekt bor:
const fromServer = JSON.parse(
'{"type": "img", "props": {"src": "x"}}'
);
function App() {
return <p>{fromServer}</p>;
}Konsolda:
Uncaught Error: Objects are not valid as a React child (found: object with keys {type, props}). If you meant to render a collection of children, use an array instead.type va props bor, lekin React uni element deb qabul qilmadi. Symbol ni JSON'da yozib bo'lmaydi — demak tashqaridan kelgan matn $$typeof li obyekt yasay olmaydi. Hujumchi o'z "elementini" serverdagi ma'lumot ichiga yashirib kiritolmaydi.
Hujumchi nigohi
Hujumchi «Bahor» saytidagi izoh maydoniga zararli matn yozadi. Uning urinishlari va React'ning javobi:
- Teg yozish (
<img onerror>,<script>) —{}dagi satr matn bo'lib chiqadi. Himoyalangan. - Soxta element (JSON'da
{type, props}) —$$typeofyo'q, React chizmaydi. Himoyalangan. javascript:havola. Mehmon profilidagi "sayt" maydonigajavascript:alert(1)yozadi va u<a href={link}>ga tushadi. React 19 bunday manzilni almashtiradi. Tekshirib ko'rdik —hrefichidajavascript:throw new Error('React has blocked a javascript: URL as a security precaution.')paydo bo'ldi: "React xavfsizlik uchunjavascript:manzilni to'sdi". Lekin bu oxirgi chiziq. Manzilni o'zingiz ham tekshiring: faqathttps:bilan boshlanganini qabul qiling.- HTML'ni ataylab qo'yish. React'da
innerHTMLning o'rnini bosuvchi atribut bor —dangerouslySetInnerHTML. Nomining o'zi ogohlantiradi: "xavfli". U himoyani butunlay o'chiradi — vanillainnerHTMLdagi hamma XSS qaytib keladi. Foydalanuvchi matnini unga hech qachon to'g'ridan-to'g'ri bermang. Qachon va qanday tozalab ishlatish — Frontend xavfsizligi React'da darsida.
Diqqat: React faqat
{}dagi matnni himoya qiladi. Atributlardagi manzil (href,src),dangerouslySetInnerHTMLva uchinchi tomon skriptlari — sizning mas'uliyatingiz. XSS va DOM xavfsizligi darsidagi CSP va Trusted Typesvazifalarda hozir ham ishlayapti — React buni o'zgartirmadi.
10. Ko'p uchraydigan xatolar
| Belgi | Sabab | Davosi |
|---|---|---|
ekranda yolg'iz 0 |
{count && …}, count = 0 |
count > 0 && yoki ternary |
ekranda NaN + ogohlantirish |
{rating && …}, rating = NaN |
Number.isNaN bilan tekshiring |
Objects are not valid as a React child |
obyekt yoki Date {} da |
maydonni tanlang: {order.dish} |
Functions are not valid as a React child |
{getPrice} |
{getPrice()} |
OshManti yopishgan |
massiv ajratuvchisiz | .join(", ") yoki <li> lar |
unique "key" prop |
.map() da key yo'q |
key={id} (Fragment'ga ham) |
Unexpected token <!-- da |
HTML izoh | {/* … */} |
11. Mashqlar
Mashqlar kurs/mashqlar/17/04-jsx-ifodalar/ da. Har yechimni «Ishga tushir» bilan sinang.
1-mashq (oson): Ekranda nima chiqadi?
Kodni ishga tushirmasdan, har qatorni oldindan ayting.
function App() {
const guests = 0;
const note = undefined;
const dishes = ["Osh", "Manti"];
return (
<div>
<p>A: {guests}</p>
<p>B: {guests && "mehmon bor"}</p>
<p>C: {note}</p>
<p>D: {dishes}</p>
<p>E: {dishes.length > 1 && "ko'p taom"}</p>
</div>
);
}- B qatorida,
B:yorlig'idan keyin: - D qatorida,
D:dan keyin: - E qatorida,
E:dan keyin:
Yechim
Ekranda:
A: 0
B: 0
C:
D: OshManti
E: ko'p taomA — son, ko'rinadi. B — 0 && … → 0, tuzoq. C — undefined, hech narsa. D — massiv, elementlari ajratuvchisiz. E — 2 > 1 → true, demak && o'ng tomonni qaytardi.
2-mashq (o'rta): Sardorning uchta xatosi
Sardor «Bahor» kassasi uchun panel yozdi. Kod yiqiladi, tuzatilsa ham ikki muammo qoladi. Uchalasini toping va tuzating: ekranda ofitsiant ismi va smenasi, buyurtma bo'lmasa "Hozircha buyurtma yo'q", menyu esa <dl> da chiqsin. Konsol toza bo'lsin.
const orders = [];
const waiter = { name: "Sardor", shift: "kechki" };
const menu = [
{ id: 1, name: "Osh", price: 35000 },
{ id: 2, name: "Lag'mon", price: 28000 },
];
function App() {
return (
<div>
<p>Ofitsiant: {waiter}</p>
<p>{orders.length && "Buyurtmalar bor"}</p>
<dl>
{menu.map((m) => (
<>
<dt>{m.name}</dt>
<dd>{m.price} so'm</dd>
</>
))}
</dl>
</div>
);
}Ishora: «Obyekt chizilmaydi», «0 && tuzog'i» va «Ro'yxatda Fragment» bo'limlari. Fragment'ga key uchun nimani import qilish kerak?
Yechim
import { Fragment } from "react";
const orders = [];
const waiter = { name: "Sardor", shift: "kechki" };
const menu = [
{ id: 1, name: "Osh", price: 35000 },
{ id: 2, name: "Lag'mon", price: 28000 },
];
function App() {
return (
<div>
<p>Ofitsiant: {waiter.name} ({waiter.shift} smena)</p>
<p>
{orders.length > 0
? `${orders.length} ta buyurtma`
: "Hozircha buyurtma yo'q"}
</p>
<dl>
{menu.map((m) => (
<Fragment key={m.id}>
<dt>{m.name}</dt>
<dd>{m.price} so'm</dd>
</Fragment>
))}
</dl>
</div>
);
}Ekranda:
Ofitsiant: Sardor (kechki smena)
Hozircha buyurtma yo'q
Osh
35000 so'm
Lag'mon
28000 so'm{waiter}— obyekt, komponent yiqiladi. Maydonlarini chiqardik.{orders.length && …}— bo'sh massivda0. Taqqoslash va ternary.<>gakeyberib bo'lmaydi —Fragmentimport qilindi.
3-mashq (qiyin): Har qiymatni xavfsiz ko'rsatadigan yordamchi
«Bahor» dasturchilari uchun "kuzatuv paneli" yasang: unda turli qiymatlar va ularning ekrandagi ko'rinishi turadi. TypeScript'da showValue(value: unknown): string | number funksiyasini yozing. Talablar:
null,undefined,NaNva bo'sh satr →"—";- boolean →
"ha"yoki"yo'q"(React ularni yashirgani uchun); - son va satr — o'zicha;
- massiv → elementlari
", "bilan (har element ham shu qoidalar bilan); - qolgan hamma narsa (obyekt) →
JSON.stringify.
Panel <dl> bo'lsin: har qiymatga <dt> (nomi) va <dd> (ko'rinishi), ro'yxat <Fragment key> bilan. Ishora: unknown ni typeof va Array.isArray bilan toraytiring (Narrowing: turni toraytirish darsi). string | number — ReactNode ning bir qismi, shuning uchun natijani {} ga bemalol qo'yasiz.
Yechim
import { Fragment } from "react";
function showValue(value: unknown): string | number {
if (value === null || value === undefined) return "—";
if (typeof value === "number") {
return Number.isNaN(value) ? "—" : value;
}
if (typeof value === "string") return value === "" ? "—" : value;
if (typeof value === "boolean") return value ? "ha" : "yo'q";
if (Array.isArray(value)) return value.map(showValue).join(", ");
return JSON.stringify(value);
}
const samples: [string, unknown][] = [
["Mehmonlar", 0],
["Reyting", NaN],
["Izoh", null],
["Ochiqmi", true],
["Taomlar", ["Osh", "Manti"]],
["Buyurtma", { dish: "Osh", soni: 2 }],
];
export default function App() {
return (
<dl>
{samples.map(([label, value]) => (
<Fragment key={label}>
<dt>{label}</dt>
<dd>{showValue(value)}</dd>
</Fragment>
))}
</dl>
);
}Ekranda:
Mehmonlar
0
Reyting
—
Izoh
—
Ochiqmi
ha
Taomlar
Osh, Manti
Buyurtma
{"dish":"Osh","soni":2}Tekshiruv tartibi muhim: NaN ning turi number, shuning uchun u son tekshiruvi ichida ushlanadi. Massiv typeof da "object" — u JSON.stringify dan oldin tekshirilishi shart. value.map(showValue) — har element uchun o'sha funksiya (rekursiya). JSON.stringify natijasi satr — satr esa React'da xavfsiz: ichida <script> bo'lsa ham matn bo'lib chiqadi.
12. Real ishda
0 &&— kod ko'rigida (code review) tez-tez belgilanadigan xato. Uni avtomatik ushlash uchun lint qoidasi ham bor:eslint-plugin-reactdagireact/jsx-no-leaked-render("render'ga sizib chiqqan qiymat").- Fragment — jadval, ro'yxat va Flexbox/Grid maketlarida har kuni: ortiqcha
<div>CSS'ni buzadi va DOM'ni og'irlashtiradi. - XSS: React'da matnni chiqarish sukut bo'yicha xavfsiz — vanilla
innerHTMLdagi xatoni tasodifan qilib bo'lmaydi. Shuning uchun xavfsizlik tekshiruvida (security review) birinchi qidiriladigan joylar —dangerouslySetInnerHTMLva foydalanuvchidan kelganhref. - Intervyu savollari: "
{count && <X/>}nega0chiqaradi?", "React qaysi qiymatlarni chizmaydi?", "Fragment nima va qachonkeykerak?", "React XSS'dan qanday himoya qiladi va qayerda himoya qilmaydi?".
Xulosa
{}ichida istalgan ifoda; natija turiga qarab chiziladi.null,undefined,true,false,""— hech narsa; satr va son — matn; massiv — elementlari ketma-ket.0vaNaNko'rinadi:&&chapida son bo'lsa —> 0bilan taqqoslang yoki ternary ishlating. TypeScript bu tuzoqni ushlamaydi.- Oddiy obyekt va
Date— xato, funksiya — ogohlantirish;ReactNodeturi ikkalasini ham rad etadi. <>…</>DOM'ga hech narsa qo'shmaydi; ro'yxatda<Fragment key={…}>. Izoh —{/* … */}.{}dagi satr hech qachon HTML bo'lib o'qilmaydi;dangerouslySetInnerHTMLbu himoyani o'chiradi.
Keyingi dars: Komponentlar: yaratish, nomlash va fayllarga ajratish — JSX qaytaradigan funksiyalarni o'z komponentlarimizga aylantiramiz, katta harf qoidasini va fayllarga bo'lishni o'rganamiz.
Manbalar
- React: "JavaScript in JSX with Curly Braces", "Conditional Rendering" (
0 &&tuzog'i), "Rendering Lists" — react.dev/learn - React:
<Fragment>(<>...</>) — react.dev/reference/react/Fragment - React: "Common components" —
dangerouslySetInnerHTMLogohlantirishi — react.dev/reference/react-dom/components/common - Dan Abramov: "Why Do React Elements Have a $$typeof Property?" (2018-12-03) — overreacted.io
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!