image Привет, Хаброжители! Хотите создавать эффективные приложения с помощью React? Тогда эта книга написана для вас. Познакомьтесь c лучшими практиками и шаблонами создания современного кода.

Вам не потребуются глубокие знания React или функционала JavaScript — достаточно знакомства с принципами работы JavaScript, CSS и HTML.

Алекс Бэнкс и Ева Порселло научат вас создавать пользовательские интерфейсы, которые будут динамически отображать изменения без необходимости перезагрузки страницы даже на крупномасштабных сайтах, работающих с огромными массивами данных.

В этой книге вы:

  • Разберетесь с ключевыми аспектами функционального программирования на JavaScript.
  • Узнаете, как устроена работа React в браузере.
  • Создадите слои представления приложения с помощью компонентов React.
  • Научитесь управлять данными и тратить меньше времени на отладку.
  • Внедрите в проект хуки React для управления состояниями и перехвата данных.
  • Используете маршрутизатор для полноценной работы с одностраничными приложениями.
  • Научитесь структурировать приложения React с учетом особенности работы сервера.

Как работает React


Итак, мы изучили последний актуальный синтаксис и ознакомились с паттернами функционального программирования, лежащими в основе React. Теперь перейдем к следующему шагу — а именно к нашей цели: изучению работы React. Приступим к написанию реального кода на React.

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

Настройка страницы


Для работы с React в браузере необходимо импортировать две библиотеки: React и ReactDOM. React — это библиотека для создания представлений. ReactDOM — это библиотека для рендеринга пользовательского интерфейса в браузере. Обе библиотеки доступны в виде сценариев из распакованного CDN (ссылки приведены в коде ниже). Создадим HTML-документ:

<!DOCTYPE html>
<html>
  <head>
     <meta charset="utf-8" />
     <title>React Samples</title>
  </head>
  <body>
     <!-- Target container -->
     <div id="root"></div>
     <!-- React library & ReactDOM (Development Version)-->
     <script
src="https://unpkg.com/react@16/umd/react.development.js">
     </script>
<script
src="https://unpkg.com/react-dom@16/umd/react-dom.development.js">
</script>

    <script>
          // Pure React and JavaScript code
    </script>
  </body>
</html>

Это минимальные требования для работы с React в браузере. Можно разместить свой сценарий JavaScript в отдельном файле, но он должен быть загружен где-нибудь на странице после загрузки React. Мы собираемся использовать версию React для разработки, чтобы все сообщения об ошибках и предупреждения выводились в консоли браузера. Вы можете использовать уменьшенную релизную версию (react.production.min.js и react.production.min.js), если захотите убрать предупреждения.

Элементы React


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

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

<section id="baked-salmon">
   <h1>Baked Salmon</h1>
   <ul class="ingredients">
      <li>2 lb salmon</li>
      <li>5 sprigs fresh rosemary</li>
      <li>2 tablespoons olive oil</li>
      <li>2 small lemons</li>
      <li>1 teaspoon kosher salt</li>
      <li>4 cloves of chopped garlic</li>
   </ul>
   <section class="instructions">
      <h2>Cooking Instructions</h2>
      <p>Preheat the oven to 375 degrees.</p>
      <p>Lightly coat aluminum foil with oil.</p>
      <p>Place salmon on foil</p>
      <p>Cover with rosemary, sliced lemons, chopped garlic.</p>
      <p>Bake for 15-20 minutes until cooked through.</p>
      <p>Remove from oven.</p>
    </section>
</section>

В HTML элементы связаны друг с другом в иерархии, напоминающей генеалогическое древо. Можно сказать, что у корневого элемента (в данном случае раздела) есть три дочерних элемента: заголовок, неупорядоченный список ингредиентов и раздел для инструкций.

В прошлом веб-сайты состояли из отдельных HTML-страниц. Когда пользователь перемещался по этим страницам, браузер запрашивал и загружал различные HTML-документы. Изобретение AJAX (асинхронного JavaScript и XML) подарило нам одностраничные приложения, или SPA (https://ru.wikipedia.org/wiki/Одностраничное_приложение). Поскольку браузеры теперь могут с помощью AJAX запрашивать и загружать маленькие фрагменты данных, целые веб-приложения теперь могут работать на одной странице и обновлять пользовательский интерфейс инструментами JavaScript.

В SPA браузер изначально загружает один HTML-документ. Перемещаясь по сайту, пользователи фактически остаются на той же странице. JavaScript уничтожает пользовательский интерфейс и создает новый всякий раз, когда пользователь взаимодействует с приложением. Может показаться, что вы перемещаетесь со страницы на страницу, но на самом деле вы находитесь на одной HTML-странице, а JavaScript выполняет всю работу.

DOM API (https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model) представляет собой набор объектов, которые JavaScript может использовать при взаимодействии с браузером для изменения модели DOM. Если вы когда-либо использовали функцию document.createElement или document.appendChild, то вы уже работали с DOM API.

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

Модель DOM браузера состоит из элементов DOM. Аналогично React DOM состоит из элементов React. Элементы DOM и React на вид похожи, но на самом деле они совершенно разные. Элемент React — это описание того, как должен выглядеть фактический элемент DOM. Другими словами, элементы React — это инструкции по созданию DOM браузера.

Мы можем создать элемент React для представления тега h1с с помощью функции React.createElement:

React.createElement("h1", { id: "recipe-0" }, "Baked Salmon");

Первый аргумент определяет тип элемента, который мы хотим создать — в данном случае h1. Второй аргумент определяет свойства элемента. Элемент h1 имеет идентификатор recipe-0. Третий аргумент соответствует дочерним элементам: это могут быть любые узлы, вставленные между открывающим и закрывающим тегами (в данном случае только некоторый текст).

Во время рендеринга React преобразует этот элемент в реальный элемент DOM:

<h1 id="recipe-0">Baked Salmon</h1>

Свойства аналогичным образом применяются к новому элементу DOM: они добавляются к тегу как атрибуты, а дочерний текст добавляется как текст внутри элемента. Элемент React — это просто литерал JavaScript, который сообщает React, как создать элемент DOM.

В журнале этот элемент выглядит так:

{
   $$typeof: Symbol(React.element),
   "type": "h1",
   "key": null,
   "ref": null,
   "props": {id: "recipe-0", children: "Baked Salmon"},
   "_owner": null,
   "_store": {}
}

Именно так выглядит структура элемента React. Некоторые поля используются самим React: _owner, _store, и $$typeof. Поля key и ref тоже важны для элементов React, но мы познакомимся с ними позже. А пока подробнее рассмотрим поля type и props.

Свойство type элемента React сообщает React, какой тип элемента HTML или SVG нужно создать. Свойство props содержит данные и дочерние элементы, необходимые для создания элемента DOM. Свойство children предназначено для рендеринга других вложенных элементов в виде текста.
СОЗДАНИЕ ЭЛЕМЕНТОВ
Мы заглядываем в объект, который возвращает функция React.createElement. Но создавать подобные элементы вручную не нужно, вместо этого вы всегда будете использовать функцию React.createElement.

ReactDOM


Создав элемент React, мы захотим увидеть его в браузере. ReactDOM содержит необходимые для этого инструменты, например метод render.

Мы можем отобразить элемент React и его дочерние элементы в DOM с помощью метода React DOM.render. Для этого мы передадим этот элемент в качестве первого аргумента, а вторым аргументом будет целевой узел, в котором нужно отобразить элемент:

const dish = React.createElement("h1", null, "Baked Salmon");

ReactDOM.render(dish, document.getElementById("root"));

Рендеринг элемента title в DOM добавит элемент h1 в div с идентификатором root, который мы уже определили в нашем HTML. Этот div размещается внутри тега body:

<body>
  <div id="root">
    <h1>Baked Salmon</h1>
  </div>
</body>

Все, что связано с рендерингом элементов в DOM, находится в пакете ReactDOM. В версиях React вплоть до React 16 в DOM можно было отображать только один элемент. Сегодня можно также отображать массивы. Когда такая возможность была анонсирована на ReactConf 2017, все аплодировали и кричали. Это было большое дело. Вот как оно выглядит:

const dish = React.createElement("h1", null, "Baked Salmon");
const dessert = React.createElement("h2", null, "Coconut Cream Pie");

ReactDOM.render([dish, dessert], document.getElementById("root"));

Этот код отобразит оба элемента как одноуровневые внутри корневого контейнера. Надеемся, вы тоже аплодируете и кричите!

В следующем разделе мы узнаем, как использовать метод props.children.

Потомки


React отображает дочерние элементы с помощью метода props.children. В предыдущем разделе мы отобразили текстовый элемент как дочерний элемента h1, и поэтому для метода props.children было установлено значение «Baked Salmon». Мы можем отображать другие элементы React как дочерние, создавая дерево элементов. Вот почему мы используем термин дерево элементов: у него есть один корневой элемент, от которого вырастает множество ветвей.

Рассмотрим неупорядоченный список ингредиентов:

<ul>
   <li>2 lb salmon</li>
   <li>5 sprigs fresh rosemary</li>
   <li>2 tablespoons olive oil</li>
   <li>2 small lemons</li>
   <li>1 teaspoon kosher salt</li>
   <li>4 cloves of chopped garlic</li>
</ul>

В этом примере неупорядоченный список является корневым элементом и имеет шесть дочерних элементов. Мы можем представить этот ul и его дочерние элементы с помощью React.createElement:

React.createElement(
   "ul",
    null,
    React.createElement("li", null, "2 lb salmon"),
    React.createElement("li", null, "5 sprigs fresh rosemary"),
    React.createElement("li", null, "2 tablespoons olive oil"),
    React.createElement("li", null, "2 small lemons"),
    React.createElement("li", null, "1 teaspoon kosher salt"),
    React.createElement("li", null, "4 cloves of chopped garlic")
);

Каждый дополнительный аргумент, передаваемый функции createElement, является еще одним дочерним элементом. React создает массив этих дочерних элементов и устанавливает для него значение props.children.

Проверив получившийся элемент React, мы увидим, что каждый элемент списка представлен элементом React и добавлен в массив props.children. Если мы выведем этот элемент в журнал:

const list = React.createElement(
    "ul",
    null,
    React.createElement("li", null, "2 lb salmon"),
    React.createElement("li", null, "5 sprigs fresh rosemary"),
    React.createElement("li", null, "2 tablespoons olive oil"),
    React.createElement("li", null, "2 small lemons"),
    React.createElement("li", null, "1 teaspoon kosher salt"),
    React.createElement("li", null, "4 cloves of chopped garlic")
);

console.log(list);

то результат будет таким:

{
    "type": "ul",
    "props": {
    "children": [
    { "type": "li", "props": { "children": "2 lb salmon" } … },
    { "type": "li", "props": { "children": "5 sprigs fresh rosemary"} … },
    { "type": "li", "props": { "children": "2 tablespoons olive oil" } … },
    { "type": "li", "props": { "children": "2 small lemons"} … },
    { "type": "li", "props": { "children": "1 teaspoon kosher salt"} … },
    { "type": "li", "props": { "children": "4 cloves of chopped garlic"} … }
    ]
    ...
    }
}

Теперь видно, что каждый элемент списка является дочерним. Ранее в этой главе мы писали код HTML для всего рецепта, расположив его в элементе section. Чтобы повторить это с помощью React, мы будем использовать серию вызовов createElement:

React.createElement(
    "section",
    { id: "baked-salmon" },
    React.createElement("h1", null, "Baked Salmon"),
    React.createElement(
       "ul",
    { className: "ingredients" },
     React.createElement("li", null, "2 lb salmon"),
     React.createElement("li", null, "5 sprigs fresh rosemary"),
     React.createElement("li", null, "2 tablespoons olive oil"),
     React.createElement("li", null, "2 small lemons"),
     React.createElement("li", null, "1 teaspoon kosher salt"),
     React.createElement("li", null, "4 cloves of chopped garlic")
 ),
 React.createElement(
     "section",
     { className: "instructions" },
     React.createElement("h2", null, "Cooking Instructions"),
     React.createElement("p", null, "Preheat the oven to 375 degrees."),
     React.createElement("p", null, "Lightly coat aluminum foil with oil."),
     React.createElement("p", null, "Place salmon on foil."),
     React.createElement(
        "p",
        null,
       "Cover with rosemary, sliced lemons, chopped garlic."
),
      React.createElement(
       "p",
       null,
      "Bake for 15-20 minutes until cooked through."
    ),
    React.createElement("p", null, "Remove from oven.")
    )
 );

CLASSNAME В REACT
Любой элемент, имеющий атрибут HTML class, использует свойство className вместо class, поскольку class — зарезервированное слово в JavaScript. Вот так выглядит чистый код React. В конечном итоге чистый код React — это то, что работает в браузере. Приложение React — это дерево элементов React, которые происходят из одного корневого элемента. Элементы React — это инструкции, которые React будет использовать для создания пользовательского интерфейса в браузере.

Создание элементов с данными


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

Вернемся назад и вспомним о неупорядоченном списке:

React.createElement(
    "ul",
    null,
    React.createElement("li", null, "2 lb salmon"),
    React.createElement("li", null, "5 sprigs fresh rosemary"),
    React.createElement("li", null, "2 tablespoons olive oil"),
    React.createElement("li", null, "2 small lemons"),
    React.createElement("li", null, "1 teaspoon kosher salt"),
    React.createElement("li", null, "4 cloves of chopped garlic")
);

Данные, используемые в этом списке ингредиентов, можно представить с помощью массива JavaScript:

const items = [ 
    "2 lb salmon",
    "5 sprigs fresh rosemary",
    "2 tablespoons olive oil",
    "2 small lemons",
    "1 teaspoon kosher salt",
    "4 cloves of chopped garlic"
];

Из этих данных можно создать список с правильным количеством элементов без необходимости жесткого кодирования каждого из них. Мы можем отображать массив и создавать элементы списка для любого количества ингредиентов:

React.createElement(
     "ul",
     { className: "ingredients" },
     items.map(ingredient => React.createElement("li", null, ingredient))
);

Этот синтаксис создает элемент React для каждого ингредиента в массиве. Каждая строка отображается в дочерних элементах списка как текст. Значение для каждого ингредиента отображается как элемент списка.

При запуске этого кода вы увидите предупреждение консоли, подобное показанному на рис. 4.1.

image

Когда мы создаем список дочерних элементов путем итерации по массиву, React хочет, чтобы каждый из них имел свойство key. Свойство key помогает React эффективно обновлять DOM. Вы можете убрать это предупреждение, добавив уникальное свойство key для каждого элемента записи списка. Вы можете использовать индекс массива для каждого ингредиента как уникальное значение:

React.createElement(
    "ul",
    { className: "ingredients" },
    items.map((ingredient, i) =>
       React.createElement("li", { key: i }, ingredient)
    )
);

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

Более подробно с книгой можно ознакомиться на сайте издательства
» Оглавление
» Отрывок

Для Хаброжителей скидка 25% по купону — React

По факту оплаты бумажной версии книги на e-mail высылается электронная книга.

Комментарии (3)


  1. CyberN_O_o_b
    14.09.2021 16:58

    а тут точно про современное говорится?
    хуки охватываются ?


    1. laisto
      14.09.2021 20:37

      >Внедрите в проект хуки React для управления состояниями и перехвата данных.

      эта строчка вроде как намекает


    1. ph_piter Автор
      15.09.2021 11:18

      Глава 7

      Улучшение компонентов с помощью хуков