React JSX выглядае як HTML — ён компілюецца у JavaScript.
JSX — это маркап языка JavaScript: адзін коранавой элемент, закрытыя тэгі, атрыбуты у формате camelCase і круглыя скобкі для выразаў — з класычнымі правіламі, з якімая сталкаюцца пачатківцы.
JSX выглядае як HTML у файле компанента, але ён кампілюецца у JavaScript — і гэты факт пояснюе практычна всі правілы синтаксису.
У паканяніх роздзелах частаюць адносіць маркап, які вяртае компанент — напрыклад <h1>Hello</h1> — да неформальнага тэрміна „маркап“. Насправды ж гэта JSX. Мета простая: спрацавляць з JSX як з JavaScript, який простаўляеся як HTML. Калі гэта стане зрозумелым, большасць видных правіл синтаксису перестае здавацца довільнымі.
Чаму JSX — маркап і логіка разам
У класычным фронт-енд развіцці структура знаходзілася ў файлах HTML, а поведзенне — у файлах JavaScript. У практыцы важка адделіць выгляд кнопкі і елемент, який обрабоўвае ёё нажатыя. React размешчае і тое, і другое ў адной ейкавай — компаненте — таму яму патрэбны спосабы напісаць маркап унутро JavaScript. Гэты синтаксіс — JSX.
З візуальной точкі зоры ён супакоўваецца з HTML. Адтолькі, кампайляр ператварае JSX у JavaScript, таму правіла ў яму строгейшыя, чым у HTML. Пачніце з трох простых правілаў, якія падходзяць для пачаткуючых.
Тры правілы JSX
Правіла 1 — адна карэнная елемента
Компонент можа вярнуць толькі адну дрэва JSX. Калькі сяброўскія элементы павінны знаходзіцца пад адним карэнным элементам.
// 🔴 two siblings side by side — error
return (
<h1>Title</h1>
<p>Content</p>
);
// ✅ wrapped in one
return (
<div>
<h1>Title</h1>
<p>Content</p>
</div>
);
Якщо дадатковы <div> будзе паспяліваць DOM, абгорніце сяброўскія элементы ў Fragment (<>...</>).
return (
<>
<h1>Title</h1>
<p>Content</p>
</>
);
Чаму адна карэнная елемента? JSX становіцься значэннем у JavaScript. Функцыя не можа вярнуць два значэння адразу без іх упаковкі; тая ж ідея застосоўваецца і да JSX. Самэ тое, што ён — JavaScript, а не HTML, робіць гэтае правіла зрозумелым.
Правіла 2 — завяршваць кожную тагу
HTML дазваляе наявнасць дзеяных тагоў, такіх як <img> або <br>, без замкнучага тага. У JSX кожны таг павінен быць замкнуты. Тагі, які не маюць дзецячых элементаў, выкарыстоваюць формат самазамыкання />.
// 🔴 an HTML habit — error
<img src="logo.png">
<input type="text">
// ✅ self-closing
<img src="logo.png" />
<input type="text" />
Правіла 3 — атрыбуты у формате camelCase
Атрыбуты JSX стаюць ключамі ў об’екте JavaScript, таму іх назвы павінны адпавядаць стандартам JavaScript (camelCase), а не простым назвам HTML. Часта выступаюць супершчэпленні з резерваванымі словамі:
class→className(classў JavaScript ёсць резерваваным словам)for→htmlFor(forтаксама ёсць резерваваным словам)
// 🔴 straight from HTML
<div class="card">
<label for="email">Email</label>
</div>
// ✅ the JSX way
<div className="card">
<label htmlFor="email">Email</label>
</div>
Той жа прыемка ператварае onclick на onClick, а tabindex — на tabIndex. Не трэба запамятаваць весь спіс: адгукатар рэдагувальніка і флажок TypeScript быстра выяўляюць некоректныя назвы.
Закіркаваныя кранцы {} — JavaScript унутрь JSX
Сюды JSX перестае быць статычным шаблонам. Паколькі JSX — это JavaScript, закіркаваныя кранцы {} дозволяюць прадаўаць значэнне JavaScript на тым месцы. HTML можа хаваць толькі фіксаваны текст; JSX можа вырахоўваць выразы.
function Greeting() {
const name = 'Jane';
return <h1>Hello, {name}!</h1>; // inside the braces is JavaScript
}
{name} заменяецца на значэнне name ('Jane'). Кранцы могу прыймаць будзь-які выраз — код, який вырахоўвае значэнне — а не толькі простыя зменныя.
function Bill() {
const price = 12000;
const count = 3;
return (
<div>
<p>Unit price: {price} won</p>
<p>Quantity: {count}</p>
<p>Total: {price * count} won</p> {/* arithmetic works too */}
<p>{new Date().getFullYear()} receipt</p> {/* function calls work too */}
</div>
);
}
Кранцы таксама выкорыстоўваюцца у значэннях атрыбутаў. У такім случыку не трэба ставіць апошнія знакі ў кранцы.
function Avatar() {
const user = { name: 'Jane Kim', imageUrl: '/me.png' };
return <img src={user.imageUrl} alt={user.name} />;
}
src="..."— апостраблі означаюць буквальны строку.src={...}— квадратныя скобкі означаюць значэнне JavaScript.
Дазволены толькі выразы
Усередине квадратных скобак можна размістіць выраз, які гэнеруе значэнне. Нельга размішчаць заявы, такія як if, for чы const.
// 🔴 an if statement isn't an expression, so this fails
<p>{if (count > 0) 'in stock'}</p>
// ✅ the ternary operator is an expression, so it works
<p>{count > 0 ? 'in stock' : 'out of stock'}</p>
Умовны інтерфейс з тернарнымі выразамі, && і падобнымі шаблонамі належыць у спецыяльны роздзел пра умовную відрасліванне. Наразе дзейнічная правіла: толькі код, які гэнеруе значэнне, можа быць у квадратных скобаках.
Двойныя квадратныя скобкі {{ }} — об’ект усередине скобак
Шаблон {{ }}, які часта выкарыстоўваюцца ў JSX, не являецца окремай фічыяю мовы. Цэў об’ект JavaScript { }, які знаходзится ўнутрь зяўніх складаных краноцоў. Тыповым прыкладам являюцца стылі ўнутрь элемента.
// outer { } = "I'm putting JavaScript here"
// inner { } = the object itself
<div style={{ color: 'tomato', fontSize: 20 }}>styled</div>
У HTML выкарыстоўваецца строка на кшталт style="color: tomato". У JSX перадаецца об’ект, таму назвы атрыбутаў пішуцца у формате camelCase (fontSize замест font-size) а ў значэннях зазвычай выкарыстоўваюцца строкі чы рэчы. Якщо подвойныя краноцы здаюцца незрозумелымі, спачатку перакладзіце іх у зменную з іменам.
const cardStyle = { color: 'tomato', fontSize: 20 };
<div style={cardStyle}>styled</div> // exactly the same as above
Зяўні краноц означае „вставіць тут значэнне JavaScript“; внутрзяны об’ект — гэтае значэнне.
Як пісаць каментары
Каментары ўнутрь JSX таксама выкарыстоўваюць краноцы: каментар блока JavaScript, абгорнуты ў {}.
return (
<div>
{/* this is a comment inside JSX */}
<h1>Title</h1>
</div>
);
Аднаўленне всього разам
Вышэўказаныя правілы падходзяць для аднаго компонента карточкі продукту.
// src/ProductCard.tsx
function ProductCard() {
const product = {
name: 'Mechanical Keyboard',
price: 89000,
inStock: true,
imageUrl: "https://picsum.photos/200/300",
};
return (
<div className="card" style={{ padding: 16 }}>
{/* image: self-closing + brace attributes */}
<img src={product.imageUrl} alt={product.name} />
<h2>{product.name}</h2>
<p>Price: {product.price.toLocaleString()} won</p>
{/* show stock with an expression (ternary) — more in the next chapter */}
<p>{product.inStock ? 'In stock' : 'Out of stock'}</p>
</div>
);
}
export default ProductCard;
У тым прыкладзе выкарыстоўваныя ўсі тры структурныя правілы (адна коранавая елемента, закрытыя тэгі, className) і кожны распашчаты патэрн (вставка тексту, атрыбуты, арыметычныя вырачэння, трынарныя выразы, об’ект стылю).
Заключэнне
- JSX — это JavaScript, а не HTML — самэўчынна синтаксіс ёй строгейшы за HTML.
- Тры структурныя правілы: аб’еднаваць братоўскія елементы ў адну коранавую елемента (дапаможыць можа Fragment), закрываць кожны тэг, і вжываць атрыбуты у формате camelCase (
class→className,for→htmlFor). - Распашчатыя канцэвкі
{}маюць паводзіцца выразам JavaScript, будзь то ў тексте чы ў атрыбутах. - У канцэвкі могу ўжывацца толькі выразы, якія даюць значэнне — не запаведзі, такія як
ifчыfor.
{{ }} — гэта не новая сынтаксіс; гэта об’ект у скобках. Інлайн-стылі ўтвараюць класычны прыклад.Наступны логічны крок — падача даных у компонент ззовні — props. Хард-кодаванне об’екта product у самы компонент падходзіць толькі для дэманстрацыі; за дапамогою props той самы ProductCard можа атрыбутаваць многія продукты, і самэ гэта робіць типаванне ў TypeScript насупераключным.
Справы
- Документацыя React пра маркап з JSX
- Документацыя React пра вбудовванне выразаў