Головна / Статті / React JSX схожий на HTML — він компілюється у JavaScript.

React JSX схожий на HTML — він компілюється у JavaScript.

JSX — це маркап JavaScript: один кореневий елемент, закриті теги, атрибути у форматі camelCase та дужки для виразів — із класичними правилами, з якими стикаються початківці спочатку.

1208 слів

JSX схожий на HTML у файлі компонента, але він компілюється у JavaScript — і саме цей факт пояснює майже кожне правило синтаксису.

У попередніх розділах маркування, яке повертає компонент — наприклад <h1>Hello</h1> — часто розглядалося як неформальний „маркування“. Його справжнє найменування — JSX. Мета тут проста: розглядати JSX як JavaScript, який випадково схожий на HTML. Як тільки це стає зрозумілим, більшість очевидних правил синтаксису вже не здаються довільними.

Чому JSX — маркування та логіка разом

У класичному розробленні фронт-енду структура зберігалася у файлах HTML, а поведінка — у файлах JavaScript. На практиці важко розділити зовнішній вигляд кнопки та її обробник натискання. React об’єднує обидва елементи в одну одиницю — компонент, тому йому потрібен спосіб запису маркування всередині JavaScript. Цей синтаксис — JSX.

З візуальної точки зору 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 про вбудовування виразів