Menu

Что такое JSX? Правила синтаксиса JSX в React с примерами

JSX это расширение синтаксиса JavaScript, которое позволяет писать похожую на HTML разметку внутри компонентов React. Разберём его правила: один корневой элемент, закрытые теги, className, атрибуты в camelCase, фигурные скобки, инлайн-стили, комментарии и во что он компилируется.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

JSX это расширение синтаксиса JavaScript, которое позволяет писать похожую на HTML разметку прямо в коде. Компоненты React возвращают JSX, чтобы описать, что должно появиться на экране, а инструмент сборки компилирует его в обычные вызовы функций JavaScript. Он похож на HTML, но несколько правил отличаются, а фигурные скобки позволяют вставить в разметку любое значение JavaScript.

Всё внутри {} это JavaScript: свойство, вызов метода и даже map, превращающий массив в элементы списка. Добавьте 'design' в массив skills, и обновятся и счётчик, и список.

Правила JSX

Возвращайте один корневой элемент

Компонент возвращает одно значение, поэтому его JSX нужен один родитель. Два соседних элемента на верхнем уровне дают синтаксическую ошибку. Если вы не хотите лишний <div> на странице, оберните их во фрагмент, <>...</>:

// Error: Adjacent JSX elements must be wrapped in an enclosing tag
return (
    <h1>Title</h1>
    <p>Text</p>
);

// OK: a fragment groups them without adding a DOM element
return (
    <>
        <h1>Title</h1>
        <p>Text</p>
    </>
);

Когда группе нужен key, используйте длинную форму <Fragment key={id}>; см. фрагменты.

Закрывайте каждый тег

HTML позволяет оставлять некоторые теги открытыми. JSX нет. Элементы без детей закрываются сами через />: <img />, <br />, <input /> и ваши собственные компоненты, например <Avatar />.

Используйте className, htmlFor и атрибуты в camelCase

Атрибуты JSX становятся ключами объекта JavaScript, поэтому подчиняются правилам именования JavaScript. class и for это зарезервированные слова в JavaScript, поэтому JSX использует className и htmlFor. Атрибуты из нескольких слов и все обработчики событий пишутся в camelCase: tabIndex, maxLength, autoFocus, onClick, onChange. Два исключения сохраняют дефисы: атрибуты aria-* и data-* пишутся в точности как в HTML.

Замените className="field" на class="field". Подпись сохранит стиль, потому что React всё равно задаёт атрибут, но сборка для разработки выведет "Invalid DOM property class. Did you mean className?" Превью работает как продакшен-сборка, поэтому здесь вы этого предупреждения не увидите; используйте className. Строковый атрибут пишется в кавычках (type="email"), любое другое значение в фигурных скобках (maxLength={40}, disabled={false}).

Фигурные скобки принимают выражения, а не инструкции

Внутри {} можно написать всё, что даёт значение: переменную, арифметику, вызов функции, тернарный оператор, &&, шаблонную строку. Инструкции вроде if, for и const значения не дают, поэтому туда их поставить нельзя. Сделайте работу до return или используйте форму выражения:

Присмотритесь, прежде чем нажимать: на странице виден лишний 0. count && <p>...</p> даёт 0, когда счётчик равен нулю, а React рендерит числа, даже ноль. Замените на count > 0 && <p>You have mail.</p>, и 0 исчезнет. false, null, undefined и true ничего не рендерят, поэтому булево значение слева от && безопасно. Шаблоны разобраны на странице об условном рендеринге.

Инлайн-стили задаются объектом

Атрибут style принимает объект JavaScript, а не строку CSS. Отсюда вид «двойных скобок»: внешняя пара означает «здесь JavaScript», внутренняя это литерал объекта. Имена свойств пишутся в camelCase (backgroundColor, fontSize), а простое число для большинства свойств размера означает пиксели.

Раз стиль это объект, его можно вычислить из состояния, как любое другое значение. Попробуйте заменить fontSize: big ? 24 : 16 на fontSize: big ? '2em' : '1em': строки передаются вместе с единицей измерения.

Комментарии

Комментарий внутри JSX пишется в фигурных скобках: {/* this is a comment */}. Комментарии HTML (<!-- -->) дают синтаксическую ошибку. Вне разметки, в теле функции, обычные комментарии // работают как всегда.

return (
    <div>
        {/* The header is hidden on small screens */}
        <Header />
    </div>
);

Как перевести HTML в JSX

Вставить HTML в компонент это частый первый шаг, и большая его часть работает. Вот изменения, которые обычно приходится внести:

  • class становится className, а for становится htmlFor.
  • Пустые теги закрываются сами: <br> становится <br />, <img src="a.png"> становится <img src="a.png" />.
  • style="color: red; font-size: 14px" становится style={{ color: 'red', fontSize: 14 }}.
  • Атрибуты событий принимают функцию, а не строку: onclick="save()" становится onClick={save}.
  • Имена атрибутов переходят в camelCase: tabindex становится tabIndex, а stroke-width в SVG становится strokeWidth.
  • <!-- comments --> становятся {/* comments */}.
  • Нескольким элементам верхнего уровня нужен один родитель или фрагмент.

Онлайн-конвертеры HTML в JSX делают эти шаги за вас, но если вы их знаете, сообщения об ошибках легко читать, когда что-то пропущено.

Во что компилируется JSX

Браузеры не умеют выполнять JSX. Компилятор (например Babel, SWC или Oxc, которые Vite и фреймворки запускают за вас) превращает каждый тег в вызов функции из react/jsx-runtime:

// What you write
const element = <h1 className="title">Hello, {name}</h1>;
const button = <Button size="small">OK</Button>;
// What the compiler produces (roughly)
import { jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime';

const element = _jsxs('h1', { className: 'title', children: ['Hello, ', name] });
const button = _jsx(Button, { size: 'small', children: 'OK' });

Тег в нижнем регистре становится строкой ('h1', элемент HTML), тег с заглавной буквы становится ссылкой на вашу функцию (Button), атрибуты становятся объектом пропсов, а содержимое становится children. Старые настройки компилировали вместо этого в React.createElement(type, props, ...children), поэтому старые файлы начинаются с import React from 'react', даже если нигде не упоминают React. Вызов возвращает обычный объект, который называется элементом React. Его можно вывести в консоль:

Консоль показывает, что heading это просто данные: тип 'h3' и объект пропсов. Поэтому JSX можно хранить в переменных, передавать в функции и возвращать из них.

JSX экранирует текст за вас

Любая строка в фигурных скобках рендерится как текст, а не как HTML. Если пользователь введёт <img src=x onerror=alert(1)> в поле комментария, React покажет эти символы на экране, а не создаст тег изображения. По умолчанию это блокирует самую распространённую форму межсайтового скриптинга (XSS).

Первый абзац выводит теги как обычные символы. Второй использует dangerouslySetInnerHTML, который пропускает экранирование и вставляет строку как настоящий HTML, поэтому «our own» выделено жирным. Длинное имя это предупреждение: передавайте туда только HTML, который вы создали сами или очистили санитайзером, например DOMPurify. Передача туда пользовательского ввода снова открывает дыру XSS, которую закрыл JSX.

Часто задаваемые вопросы

Как расшифровывается JSX?

JSX означает JavaScript XML. Это расширение синтаксиса, которое позволяет писать похожую на HTML разметку внутри кода JavaScript.

JSX это HTML?

Нет. JSX похож на HTML, но компилируется в вызовы функций JavaScript, которые создают элементы React. Поэтому в нём используется className вместо class, имена атрибутов в camelCase, и каждый тег должен быть закрыт.

Можно ли использовать React без JSX?

Да. JSX необязателен: можно напрямую вызывать createElement('h1', { className: 'title' }, 'Hello') из react. Почти каждый проект на React использует JSX, потому что вложенную разметку так гораздо легче читать.

Почему внутри JSX нельзя использовать if?

Фигурные скобки в JSX принимают выражения, то есть то, что даёт значение, а if это инструкция. Используйте тернарный оператор (cond ? a : b), && или вычислите значение в переменной до return.

Как написать комментарий в JSX?

Оберните комментарий JavaScript в фигурные скобки: {/* вот так */}. Комментарии HTML (<!-- -->) в JSX дают синтаксическую ошибку.

Иллюстрация языков программирования Coddy

Учитесь программировать с Coddy

НАЧАТЬ