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

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

… Определить краткий и знакомый синтаксис для определения древовидной структуры с атрибутами. ~ Спецификация JSX

Теперь вы, вероятно, говорите себе: «Привет, Райан, это звучит здорово, но уже перейди к коду», и вот наш первый пример.

const helloWorld = <h1>Hello, World!</h1>;

Вот и все!

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

Хотя вам не обязательно использовать JSX при написании React (или используйте React, чтобы попробовать JSX), нельзя отрицать, что это важная часть экосистемы React, поэтому давайте погрузимся и посмотрим, что происходит под капотом. .

Начало работы с JSX

Первое, на что следует обратить внимание при использовании синтаксиса JSX, - это то, что React должен быть в области видимости. Это связано с тем, как он компилируется. Возьмем, к примеру, этот компонент:

function Hello() {
  return <h1>Hello, World!</h1>
}

За кулисами каждый элемент, отображаемый компонентом Hello, преобразуется в вызов React.createElement.

В этом случае:

function Hello() {
  return React.createElement("h1", {}, "Hello, World!")
}

То же верно и для вложенных элементов. В двух приведенных ниже примерах в конечном итоге будет отображаться одна и та же разметка.

// Example 1: Using JSX syntax
function Nav() {
  return (
    <ul>
      <li>Home</li>
      <li>About</li>
      <li>Portfolio</li>
      <li>Contact</li>
    </ul>
  );
}
// Example 2: Not using JSX syntax
function Nav() {
  return (
    React.createElement(
      "ul",
      {},
      React.createElement("li", null, "Home"),
      React.createElement("li", null, "About"),
      React.createElement("li", null, "Portfolio"),
      React.createElement("li", null, "Contact")
    )
  );
}

React.createElement

Когда React создает элементы, он вызывает этот метод, который принимает три аргумента.

  1. Имя элемента
  2. Объект, представляющий свойства элемента.
  3. Массив дочерних элементов элемента

Здесь следует отметить, что React интерпретирует элементы нижнего регистра как элементы HTML и Pascal case (например, ThisIsPascalCase) как пользовательские компоненты. Из-за этого следующие примеры можно интерпретировать по-разному.

// 1. HTML element
React.createElement("div", null, "Some content text here")
// 2. React element
React.createElement(Div, null, "Some content text here")

В первом примере будет генерироваться <div> со строкой "Some content text here" в качестве его дочернего элемента. Однако вторая версия выдала бы ошибку (если, конечно, пользовательский компонент <Div /> не входил в область действия), потому что <Div /> не определен.

Реквизит в JSX

При работе в React ваши компоненты часто визуализируют дочерние элементы, и им необходимо передавать данные, чтобы дочерние элементы могли правильно отображаться. Это так называемые реквизиты.

Мне нравится думать о компонентах React как о группе друзей. А что делают друзья? Они подпирают друг друга. К счастью, JSX предлагает нам несколько способов сделать это.

// 1. Props defaulted to true
<User loggedIn />
// 2. String literals
<User name="Jon Johnson" />
// 3. JavaScript expressions
<User balance={5 + 5 + 10} />
// 4. Spread attributes
<User preferences={...this.state} />

Но будьте осторожны! Вы не можете передавать операторы if или циклы for в качестве свойств, потому что они являются операторами, а не выражениями.

Дети в JSX

Когда вы создаете свое приложение, вы, в конечном итоге, начинаете рендерить дочерние компоненты. И затем эти компоненты иногда должны отображать дочерние элементы. И так далее.

Поскольку JSX предназначен для упрощения рассуждений о древовидной структуре элементов, он упрощает все это. По сути, любые элементы, возвращаемые компонентом, становятся его дочерними элементами.

Есть четыре способа отрисовки дочерних элементов с помощью JSX:

Струны

Это простейший пример дочерних элементов JSX. В приведенном ниже случае React создает <h1> HTML-элемент с одним дочерним элементом. Однако дочерний элемент - это не еще один элемент HTML, а всего лишь простая строка.

function AlertBanner() {
  return (
    <h1>Your bill is due in 2 days</h1>
  )
}

Элементы JSX

Вероятно, это тот вариант использования, с которым лучше всего знакомы новые разработчики React. В компоненте ниже мы возвращаем дочерний элемент HTML (<header>), у которого есть два собственных дочерних элемента <Nav /> и <ProfilePic />, оба из которых являются пользовательскими элементами JSX.

function Header(props) {
  return (
    <header>
      <Nav />
      <ProfilePic />
    </header>
  )
}

Выражения

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

Допустим, у нас есть компонент с именем <BillFooter />, который отображает информацию о счете или квитанции. Предположим, требуется одно свойство с именем total, которое представляет стоимость до налогообложения, и другое свойство taxRate, которое представляет применимую налоговую ставку.

Используя выражения, мы можем легко отображать полезную информацию для наших пользователей!

function BillFooter(props) {
  return (
    <div>
      <h5>Tax: {props.total * props.taxRate}</h5>
      <h5>Total: {props.total + props.total * props.taxRate}</h5>
    </div>
  );
}

Функции

С помощью функций мы можем программно создавать элементы и структуры, которые затем будет отображать React. Это упрощает создание нескольких экземпляров компонента или визуализацию повторяющихся элементов пользовательского интерфейса.

В качестве примера давайте воспользуемся функцией JavaScript .map() для создания панели навигации.

// Array of page information
const pages = [
  {
    id: 1,
    text: "Home",
    link: "/"
  },
  {
    id: 2,
    text: "Portfolio",
    link: "/portfolio"
  },
  {
    id: 3,
    text: "Contact",
    link: "/contact"
  }
];
// Renders a <ul> with programmatically created <li> children
function Nav() {
  return (
    <ul>
      {pages.map(page => {
        return (
          <li key={page.id}>
            <a href={page.link}>{page.text}</a>
          </li>
        );
      })}
    </ul>
  );
}

Теперь, если мы хотим добавить новую страницу на наш сайт, все, что нам нужно сделать, это добавить новый объект в массив pages, а React позаботится обо всем остальном!

Обратите внимание на key свойство. Наша функция возвращает массив элементов-братьев, в данном случае <li>s, и React нужен способ отслеживать, какие монтирования, размонтирования или обновления. Для этого он полагается на этот уникальный идентификатор для каждого элемента.

Используйте инструменты!

Конечно, вы можете писать приложения React без JSX, но я не совсем понимаю, зачем вам это нужно.

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

Итог: просто используйте JSX. Вы будете счастливы, что сделали.