Написание JSX разметки

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

You will learn

  • Почему React смешивает разметку и логику рендеринга
  • Чем JSX отличается от HTML
  • Как отображать информацию, используя JSX

JSX: Встраивание разметки в JavaScript

The Web has been built on HTML, CSS, and JavaScript. For many years, web developers kept content in HTML, design in CSS, and logic in JavaScript—often in separate files! Content was marked up inside HTML while the page’s logic lived separately in JavaScript:

Веб-сайты состоят из HTML, CSS и JavaScript. Долгое время разработчики использовали отдельные файлы: HTML для контента, CSS для дизайна и JavaScript для логики.

HTML разметка на фиолетовом фоне с тегом div и двумя дочерними тегами: p и form.
HTML разметка на фиолетовом фоне с тегом div и двумя дочерними тегами: p и form.

HTML

Три JavaScript обработчика на желтом фоне: onSubmit, onLogin, и onClick.
Три JavaScript обработчика на желтом фоне: onSubmit, onLogin, и onClick.

JavaScript

Со временем веб-сайты становились более интерактивными и логика начала определять содержание. JavaScript начал отвечать за HTML! Именно поэтому в React логика рендеринга и разметка находятся в одном месте — в компонентах.

React компонент со смешанной HTML разметкой и JavaScript из предыдущих примеров. Функция Sidebar вызывает функцию isLoggedIn, подсвечено желтым. Фиолетовым цветом подсвечен дочерний p тег из предыдущего примера и тег Form, ссылающийся на компонент, показанный в следующем примере.
React компонент со смешанной HTML разметкой и JavaScript из предыдущих примеров. Функция Sidebar вызывает функцию isLoggedIn, подсвечено желтым. Фиолетовым цветом подсвечен дочерний p тег из предыдущего примера и тег Form, ссылающийся на компонент, показанный в следующем примере.

React компонент Sidebar.js

React компонент со смешанной HTML разметкой и JavaScript из предыдущих примеров. Функция Form содержит два обработчика onClick и onSubmit на желтом фоне. Далее на фиолетовом фоне HTML разметка. HTML содержит элемент form с дочерними элементами input. Каждый input также имеет свойство onClick.
React компонент со смешанной HTML разметкой и JavaScript из предыдущих примеров. Функция Form содержит два обработчика onClick и onSubmit на желтом фоне. Далее на фиолетовом фоне HTML разметка. HTML содержит элемент form с дочерними элементами input. Каждый input также имеет свойство onClick.

React компонент Form.js

Размещая логику рендера и разметку кнопки вместе обеспечивается их синхронизация при всех дальнейших изменениях. И наоборот, размещая несвязанные детали отдельно, например разметку кнопки и разметку сайдбара, они становятся изолированными друг от друга. Поэтому дальнейшие изменение разметки одного из компонентов будет более безопасным.

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

Note

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

Конвертация HTML в JSX

Предположим, что у вас есть (полностью валидный) HTML:

<h1>Задачи Hedy Lamarr's</h1>
<img
src="https://i.imgur.com/yXOvdOSs.jpg"
alt="Hedy Lamarr"
class="photo"
>
<ul>
<li>Придумать новые светофоры
<li>Отрепетировать сцену из фильма
<li>Улучшить спектральный сенсор
</ul>

И вы хотите разместить эту разметку в компоненте:

export default function TodoList() {
return (
// ???
)
}

Если вы просто скопируете и вставите разметку, компонент не будет работать:

export default function TodoList() {
  return (
    // Этот код не работает!
    <h1>Задачи Hedy Lamarr's</h1>
    <img 
      src="https://i.imgur.com/yXOvdOSs.jpg" 
      alt="Hedy Lamarr" 
      class="photo"
    >
    <ul>
      <li>Придумать новые светофоры
      <li>Отрепетировать сцену из фильма
      <li>Улучшить спектральный сенсор
    </ul>

JSX более строгий и у него есть немного больше правил, чем у HTML! Обратите внимание на сообщение в ошибке выше, оно подскажет вам, как исправить разметку. Или просто следуйте инструкции ниже.

Note

В большинстве ситуаций ошибки React на экране подскажут вам, в чем заключается проблема. Ознакамливайтесь с ними, если у вас что-то не получается!

Правила JSX

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

Если вам нужно вернуть несколько элементов в компоненте, оберните их в один родительский тег.

Например, можно использовать <div>:

<div>
<h1>Задачи Hedy Lamarr's</h1>
<img
src="https://i.imgur.com/yXOvdOSs.jpg"
alt="Hedy Lamarr"
class="photo"
>
<ul>
...
</ul>
</div>

Если вы не хотите добавлять дополнительный <div> в разметку, можно воспользоваться тегами <> и </>:

<>
<h1>Задачи Hedy Lamarr's</h1>
<img
src="https://i.imgur.com/yXOvdOSs.jpg"
alt="Hedy Lamarr"
class="photo"
>
<ul>
...
</ul>
</>

Этот пустой тег называется Фрагмент. Фрагменты позволяют группировать элементы разметки не внедряя дополнительные теги и не изменяя древо HTML в браузере.

Deep Dive

Почему несколько JSX тегов нужно объединять?

JSX выглядит так же как HTML, но внутри конвертируется в обычные JavaScript объекты. Нельзя вернуть два объекта из функции без объединения в один массив. Это также объясняет почему нельзя возвращать два JSX тега без их объединения в один тег или Фрагмент.

2. Закрывайте все теги

JSX требует закрывать все теги: самозакрывающиеся теги, такие как <img> должны меняться на <img />, а объединяющие теги, такие как <li>oranges должны изменяться на <li>oranges</li>. Вот так изображение Hedy Lamarr и список выглядят закрытыми:

<>
<img
src="https://i.imgur.com/yXOvdOSs.jpg"
alt="Hedy Lamarr"
class="photo"
/>
<ul>
<li>Придумать новые светофоры
<li>Отрепетировать сцену из фильма
<li>Улучшить спектральный сенсор
</ul>
</>

3. Используйте camelCase для всех большинства вещей!

JSX конвертируется в JavaScript и все атрибуты становятся ключами JavaScript объекта. В компонентах вам часто потребуется считывать эти атрибуты и присваивать переменным. Но в JavaScript есть ограничения для названий переменных. Например, переменные не могут содержать тире или или называться так само, как и зарезервированные слова, например class.

Поэтому в React для большинства HTML и SVG атрибутов используется camelCase. Например, вместо stroke-width следует использовать strokeWidth. Поскольку class — зарезервированное слово, вместо него в React следует использовать className, название, соответствующее свойству DOM:

<img
src="https://i.imgur.com/yXOvdOSs.jpg"
alt="Hedy Lamarr"
className="photo"
/>

Вы можете найти все эти атрибуты в списке свойств DOM компонентов. Если вы напишите атрибут неправильно, React покажет сообщение с возможным решением проблемы в консоли браузера.

Pitfall

По историческим причинам атрибуты aria-* и data-* пишутся с тире, как и в HTML.

Подсказка: Используйте конвертор JSX

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

Вот финальный результат:

export default function TodoList() {
  return (
    <>
      <h1>Задачи Hedy Lamarr's</h1>
      <img 
        src="https://i.imgur.com/yXOvdOSs.jpg" 
        alt="Hedy Lamarr" 
        className="photo" 
      />
      <ul>
        <li>Придумать новые светофоры
        <li>Отрепетировать сцену из фильма
        <li>Улучшить спектральный сенсор
      </ul>
    </>

Recap

Теперь вы знаете, почему существует JSX и как его использовать в компонентах:

  • React компоненты объединяют логику рендеринга и разметку, потому что они связаны между собой.
  • JSX похож на HTML, но имеет свои отличия. При необходимости вы можете использовать конвертор.
  • Сообщения с ошибками зачастую направят вас в нужном направлении для решения ошибок разметки.

Challenge 1 of 1:
Конвертируйте HTML в JSX

Эта HTML разметка была перенесена в компонент, но это неправильный JSX. Исправьте его:

export default function Bio() {
  return (
    <div class="intro">
      <h1>Добро пожаловать на мой сайт!</h1>
    </div>
    <p class="summary">
      Здесь я публикую свои мысли.
      <br><br>
      <b>И <i>изображения</b></i> ученых!
    </p>
  );
}

Вы можете конвертировать HTML самостоятельно или воспользоваться конвертором.