Как установить react 17
Перейти к содержимому

Как установить react 17

  • автор:

How to Get Started With React 17 Installation in Just 5 Minutes!

Are you interested in getting started with React 17? React 17 is the latest version of the popular JavaScript library, and it offers some great new features. But getting started can be a bit daunting. In this blog post, we’ll walk you through how to install React 17 in just 5 minutes!

Step 1: Install Node.js

The first step is to install Node.js, which is a JavaScript runtime environment. You can download the latest version of Node.js from the official website. Once you’ve downloaded and installed Node.js, you’re ready to move on to the next step.

Step 2: Install Yarn

Yarn is a package manager for JavaScript. It allows you to easily install and manage packages. To install Yarn, simply run the following command in your terminal:

curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list sudo apt-get update && sudo apt-get install yarn 

Step 3: Install React 17

Now that you’ve installed Node.js and Yarn, you’re ready to install React 17. To do this, simply run the following command in your terminal:

yarn add react@17 react-dom@17 

Step 4: Create a React App

Now that you’ve installed React 17, you’re ready to create a React app. To do this, simply run the following command in your terminal:

npx create-react-app my-app 

Step 5: Start Developing!

Now that you’ve created your React app, you’re ready to start developing! To do this, simply run the following command in your terminal:

cd my-app yarn start 

You should now see your React app running in your browser. Congratulations, you’ve successfully installed React 17 in just 5 minutes! We hope this blog post has been helpful in getting you started with React 17. If you have any questions or comments, please feel free to leave them in the comments section below. Happy coding!

How to downgrade from react 18 to 17.0.2

I might not be the only one who is really scared of change in technology causing a break in my code, but you don’t have to fear anymore. with the new react 18 deployed, I will show you how to downgrade to react 17.0.2 with ease, so you can have enough time to prepare for the upgrade.

1. Create React App

  • create a folder and name it react-downgrade-2022 or whatever you want.
  • Open the terminal and run create-react-app
npx create-react-app . 

Enter fullscreen mode

Exit fullscreen mode

2. Uninstall react and react-dom

when you have created a react app it will come with react 18 and react-dom 18, but this is not what we want since we are trying to downgrade to react 17.0.2 and react-dom 17.0.2

 "name": "react-downgrade-2022", "version": "0.1.0", "private": true, "dependencies":  "@testing-library/jest-dom": "^5.16.4", "@testing-library/react": "^13.0.1", "@testing-library/user-event": "^13.5.0", "react": "^18.0.0", // "react-dom": "^18.0.0", // "react-scripts": "5.0.1", "web-vitals": "^2.1.4" >, "scripts":  "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" >, "eslintConfig":  "extends": [ "react-app", "react-app/jest" ] >, "browserslist":  "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] > > 

Enter fullscreen mode

Exit fullscreen mode

we would have to uninstall react 18 and react-dom 18, now run
npm uninstall react react-dom

npm uninstall react react-dom 

Enter fullscreen mode

Exit fullscreen mode

this is done so that we can get rid of react 18 and react-dom 18, remember, we are trying to downgrade to react 17 and react-dom 17.

3 Install react 17 and react-dom 17

now to get what we really want which is react 17 and react-dom 17 once again, run npm install react@17.0.2 react-dom@17.0.2

npm install react@17.0.2 react-dom@17.0.2 

Enter fullscreen mode

Exit fullscreen mode

React will yell at you with some deprecated warning signs, ignore whatever warning signs that are shown.

4 Change index.js

Remember, because we had already installed react 18, index.js will come with some default react 18 settings, which we would have to change to match that of react 17.0.2

navigate to your index.js file in the src directory.

 // react 18 import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css'; import App from './App'; import reportWebVitals from './reportWebVitals'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( React.StrictMode> App /> /React.StrictMode> ); // If you want to start measuring performance in your app, pass a function // to log results (for example: reportWebVitals(console.log)) // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals reportWebVitals(); 

Enter fullscreen mode

Exit fullscreen mode

now copy and paste the below code to your index.js file

 // react 17.0.2 import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; ReactDOM.render( React.StrictMode> App/> /React.StrictMode>, document.getElementById('root') ); 

Enter fullscreen mode

Exit fullscreen mode

5 finish

now, we have successfully downgraded from react 18 to react 17.0.2
run npm start

npm start 

Enter fullscreen mode

Exit fullscreen mode

Thank you, Please follow me

Предварительная версия React 17: обошлись без новой функциональности

Предварительная версия React 17: обошлись без новой функциональности главное изображение

10 августа мы выпустили первый релиз-кандидат (предварительную версию) React 17. С момента последнего мажорного обновления React прошло 2.5 года, а это много по нашим стандартам. В этой статье расскажем, какова роль этого обновления, каких изменений от него ожидать и как протестировать предварительную версию React 17.

Обошлись без новой функциональности

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

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

В частности, React 17 — «релиз-ступень», которая обеспечивает безопасное встраивание дерева, управляемого одной версией React, в дерево, которое управляется другой версией React.

Постепенные обновления

В последние 7 лет обновления версий React работали по принципу «всё или ничего». Вы либо работаете со старой версией, либо обновляете приложение, и оно полностью работает на новой версии. Промежуточных вариантов не было.

Пока это работает, но стратегия «всё или ничего» ограничивает нас. Некоторые изменения API, например, отказ от устаревшего API Context , невозможно выполнить автоматически. Большинство написанных в последнее время приложений не используют устаревшие API, но мы всё равно поддерживаем их. Мы вынуждены выбирать межу поддержкой устаревшей функциональности в React и необходимостью навсегда оставить некоторые приложения на старых версиях React. Оба варианта неудачные.

Поэтому мы сделали новую опцию.

React 17 позволяет обновляться постепенно. Когда вы обновляетесь с версии 15 на 16 (или, в будущем, с версии 16 на 17), обычно вы обновляете всё приложение. Это отлично работает во многих случаях. Но такой подход может стать проблемой, если кодовая база была написана несколько лет назад и не поддерживалась. Использовать разные версии React на одной странице можно было и раньше. Но до React 17 такой подход делал код хрупким и вызывал проблемы с событиями.

Мы решили многие из этих проблем с помощью React 17. То есть после выхода React 18 и других версий в будущем у вас появится больше возможностей. Одна из них — обновлять приложение полностью, как это происходило раньше. Но у вас появится и возможность обновлять приложение по частям. Например, вы сможете обновить приложение до будущей версии React 18, но оставить на React 17 некоторые диалоги или вложенные роуты с отложенной загрузкой.

Это не значит, что вы должны использовать постепенные обновления. Лучшей стратегией для большинства приложений по-прежнему будет одномоментный переход на новую версию. Загрузку двух версий React нельзя назвать хорошим идеальным решением, даже если одна из них загружается лениво по требованию. Но для больших приложений, которые не поддерживаются активно, этот подход имеет смысл. А React 17 позволяет таким приложениям не устаревать безнадёжно.

Чтобы использовать поэтапное обновление, вам нужно внести некоторые изменения в систему обработки событий React. React 17 — мажорный релиз, так как реализованные в нём изменения потенциально критические. На деле нам пришлось изменить менее чем 20 компонентов из более чем 100 тыс. Поэтому мы ожидаем, что большинство приложений смогут мигрировать на новую версию без серьёзных проблем. Сообщите нам , если вы всё-таки столкнулись с проблемами при обновлении.

На Хекслете курс по React входит в профессию «Фронтенд JavaScript». После регистрации базовые курсы в профессии, включая «Введение в программирование», «Основы командной строки», «Настройка окружения», «Системы контроля версий», можно пройти бесплатно.

Пример постепенных обновлений

Мы подготовили демо-репозиторий , в котором можно посмотреть, как при необходимости может быть реализована ленивая загрузка старой версии React. В этом репозитории используется бойлерплейт Create React App, но вы можете использовать любой другой инструмент. Пулреквесты с примерами использования других инструментов приветствуются.

Важно

Другие изменения мы отложили, они появятся после релиза React 17. Цель React 17 — сделать возможными постепенные обновления. Если обновление до React 17 было бы сложным, мы не достигли бы поставленной цели.

Изменения делегирования событий

Создание приложений с использованием разных версий React всегда было технически возможным. Однако такой подход был довольно хрупким из-за внутреннего устройства системы обработки событий.

Обычно вы вешаете обработчики событий на элементы в React-компонентах так:

button onClick=handleClick>> 

Эквивалентный код на чистом JavaScript выглядит так:

myButton.addEventListener('click', handleClick); 

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

Делегирование событий используется в React с момента появления библиотеки. Когда возникает событие в DOM, React определяет, какой компонент вызвать, а затем событие React всплывает через ваши компоненты. Но под капотом нативное событие уже всплыло на уровень document , где установлены обработчики событий React.

Однако это приводит к проблемам при постепенном обновлении.

Если вы используете на странице несколько версий React, каждая из них регистрирует обработчики событий на верхнем уровне. Это нарушает e.stopPropagation() : если вложенное дерево остановило всплытие события, внешнее дерево всё ещё получает его. Из-за этого сложно использовать разные версии React одновременно. Это не гипотетический пример — разработчики редактора Atom столкнулись с этой проблемой на практике несколько лет назад.

Именно поэтому мы поменяли внутреннее устройство привязки событий в React 17.

В React 17 событие больше не привязывается на уровне document . Вместо этого React привязывает его к контейнеру DOM, в котором отрисовывается ваше React-дерево.

const rootNode = document.getElementById('root'); ReactDOM.render(App />, rootNode); 

В React 16 и более ранних версиях используется document.addEventListener() . React 17 вместо этого использует под капотом rootNode.addEventListener() .

как под капотом работают обработчики событий в React 17

Благодаря этим изменениям теперь стало безопаснее встраивать React-дерево под управлением одной версии библиотеки внутрь дерева, которым управляет другая версия библиотеки. Чтобы это работало, обе части приложения должны использовать React 17 и выше. Поэтому обновление до React 17 играет важную роль. Говоря иначе, новый релиз — необходимая ступень, которая сделает возможными постепенные обновления.

Также описанные выше изменения позволяют проще встраивать React в приложения, созданные с использованием других технологий. Например, если внешняя «оболочка» вашего приложения написана на jQuery, но внутри более новый код написан на React, e.stopPropagation() внутри React-кода не даст событию достигнуть jQuery-кода, как вы и ожидаете. Это работает и в обратном направлении. Если вам больше не нравится React и вы хотите переписать приложение, например, на jQuery, можете переписывать внешнюю «оболочку» с React на jQuery, не опасаясь нарушить всплытие событий.

Мы подтвердили, что многочисленные проблемы, связанные с интеграцией React с другими технологиями, решаются благодаря новому поведению.

Важно

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

Устранение потенциальных проблем

Как и в других случаях выхода критических обновлений, возможно, вам придётся скорректировать код приложений. В Facebook нам пришлось изменить около 10 модулей, а всего у нас много тысяч модулей.

Например, если вы добавляете кастомные прослушиватели событий с помощью document.addEventListener(. ) , можете ожидать, что они перехватят все события React. В React 16 и более ранних версиях даже при использовании e.stopPropagation() в обработчике событий React кастомные прослушиватели всё равно получат события, потому что нативные события уже находятся на уровне document . При использовании React 17 всплытие событий будет остановлено, что и требуется, поэтому ваши обработчики на уровне document не получат их.

document.addEventListener('click', function()  // Этот обработчик больше не будет срабатывать на событиях // из React-компонентов, которые вызывают e.stopPropagation() >); 

Вы можете решить проблему, если привяжете прослушиватель к стадии погружения. Чтобы сделать это, надо передать < capture: true >третьим аргументом в document.addEventListener :

document.addEventListener('click', function()  // Теперь обработчик привязан к стадии погружения, // поэтому он получает все события click, определённые ниже >,  capture: true >); 

Обратите внимание, насколько в целом гибкий этот подход. Например, использование стадии погружения вероятно исправит ошибки в вашем коде, которые происходят при вызове e.stopPropagation() вне обработчика событий. Иными словами, всплытие событий в React 17 больше похоже на всплытие событий в DOM.

Другие критические изменения

Мы минимизировали количество критических обновлений в React 17. Например, в новой версии сохраняются все методы, которые были объявлены устаревшими в предыдущих версиях. Однако в React 17 есть другие критические обновления. Наш опыт показал относительную безопасность таких обновлений. В целом, нам пришлось изменить код менее чем в 20 модулях из более чем 100 000 тысяч.

Согласованность с браузерами

Мы внесли несколько изменений в систему событий:

  • Событие onScroll не всплывает, это позволяет решить распространённую проблему — срабатывание обработчика на родительском элементе при скроле дочернего элемента .
  • События React onFocus и onBlur теперь используют нативные события focusin и focusout под капотом. Это лучше подходит к существующему поведению React и иногда даёт дополнительную информацию.
  • Стадия погружения событий (например, onClickCapture ) сейчас использует реальные браузерные прослушиватели событий.

Эти изменения согласовывают поведение React с поведением браузеров и улучшают их взаимодействие.

Важно

Хоть React 17 под капотом перешёл с focus на focusin для события onFocus , помните, что это не повлияло на поведение при всплытии. В React событие onFocus всегда всплывало, и в новой версии это не меняется, так как в целом такое поведение более полезное. В этом примере можно увидеть разные проверки, которые можно использовать с разными вариантами использования события.

Отказ от использования пулов событий

В React 17 мы отказались от оптимизации с помощью объединения событий в пулы. Она не улучшает производительность в современных браузерах и создаёт проблемы даже для опытных React-разработчиков.

function handleChange(e)  setData(data => ( . data, // Это не работает в React 16 и более ранних версиях: text: e.target.value >)); > 

Это связано с тем, что React переиспользовал объект событий с разными событиями для повышения производительности в старых браузерах и очищал их свойства после вызова обработчика. В React 16 и более ранних версиях необходимо использовать e.persist() , чтобы извлечь событие из пула и использовать его.

В React 17 этот код работает так, как вы ожидаете. Мы полностью отказались от использования пулов событий, поэтому вы можете обратиться к полям событий в любое время, когда это необходимо.

Это изменение поведения, поэтому мы отметили это обновление как критическое. На практике мы не увидели, чтобы оно вызвало какие-то проблемы в коде Facebook. Возможно, обновление даже исправило какие-то ошибки. Заметьте, что e.persist() всё так же доступен в объекте события React, но сейчас он ничего не делает.

Тайминг сброса эффектов

Мы сделали тайминг функции сброса useEffect более согласованным.

useEffect(() =>  // Это эффект return () =>  // Это сброс. >; >); 

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

В React 16 функция сброса эффекта, если она существует, выполняется асинхронно. Мы заметили, что это неидеально для больших приложений, так как замедляет переходы на больших экранах, например, при переключении вкладок.

В React 17 функция сброса эффекта тоже запускается асинхронно. Например, если компонент размонтируется, функция сброса выполнится после обновления экрана.

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

Важно

Значит ли это, что теперь невозможно исправлять предупреждения о setState на размонтированных элементах? Не переживайте, React специально проверяет это и не запускает предупреждения о setState в промежутке между размонтированием и сбросом. Поэтому запросы отмены или интервалы почти всегда остаются одинаковыми.

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

Устранение потенциальных проблем

Мы заметили, что это обновление сломало только несколько компонентов из тысяч, хотя ещё нужно тщательно протестировать переиспользуемые библиотеки. Один из примеров проблемного кода выглядит так:

useEffect(() =>  someRef.current.someSetupMethod(); return () =>  someRef.current.someCleanupMethod(); >; >); 

Проблема в том, что someRef.current мутабельный, поэтому к моменту запуска функции сброса его значение может быть null . Чтобы решить эту проблему, можно фиксировать любые мутабельные значения внутри эффекта.

useEffect(() =>  const instance = someRef.current; instance.someSetupMethod(); return () =>  instance.someCleanupMethod(); >; >); 

Мы не думаем, что эта проблема станет распространённой, так как о ней предупреждает линтер. Убедитесь, что используете правило eslint-plugin-react-hooks .

Согласованные ошибки при возврате undefined

В React 16 и более ранних версиях возврат undefined всегда был ошибкой.

function Button()  return; // Ошибка: render ничего не возвращает. > 

Это частично связано с тем, что undefined легко вернуть непреднамеренно.

function Button()  // Мы забыли про return, поэтому компонент возвращает undefined. // React считает это ошибкой, а не игнорирует. button />; > 

Раньше React проверял возвращаемые значения из функциональных компонентов и компонентов на классах, но не проверял компоненты forwardRef и memo . Это связано с ошибкой в коде.

В React 17 компоненты forwardRef и memo ведут себя так же, как компоненты на классах и функциональные компоненты. При возврате из них undefined вы получите ошибку.

let Button = forwardRef(() =>  // Мы забыли про return, поэтому компонент возвращает undefined. // React 17 считает это ошибкой, а не игнорирует. button />; >); let Button = memo(() =>  // Мы забыли про return, поэтому компонент возвращает undefined. // React 17 считает это ошибкой, а не игнорирует. button />; >); 

В ситуациях, когда вы намеренно не хотите ничего отрисовывать, используйте null .

Нативные стеки компонентов

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

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

В React 17 мы используем другой механизм для создания стеков. Стеки компонентов создаются из нативных стеков JavaScript. Это позволяет получить удобные трассировки стеков React-компонентов в продакшен-окружении.

React обеспечил это с помощью подхода, который нельзя назвать традиционным. В настоящее время браузеры не дают доступ к стековому кадру (стек-фрейм, stack frame) функции (исходному файлу и расположению). Когда React перехватывает ошибку, он будет восстанавливать стек компонентов, выбрасывая и перехватывая временную ошибку внутри каждого из компонентов, которые находятся на более высоком уровне. Это незначительно снижает производительность при сбоях, но такое происходит только один раз на каждый тип компонентов.

Если хотите больше подробностей, посмотрите этот пулреквест . В большинстве случаев этот механизм не должен повлиять на ваш код. Разработчикам будет полезно знать о новой возможности: стеки компонентов теперь стали кликабельными, так как они созданы на основе нативных браузерных стек-фреймов. Это позволяет «расшифровать» их и найти нужную информацию об ошибках так же, как вы делаете это с обычными ошибками JavaScript.

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

Удаление приватного экспорта

Последним важным критическим изменением можно назвать удаление некоторых внутренних реализаций React, которые ранее были доступны другим проектам. Например, раньше React Native for Web зависел от внутренних реализаций системы событий. Но эти зависимости были хрупкими и часто ломались.

В React 17 мы удалили такие приватные экспорты. Насколько нам известно, React Native for Web был единственным проектом, который их использует. И этот проект уже использует другие инструменты, которые не зависят от этих приватных экспортов.

Это значит, что старые версии React Native for Web будут несовместимыми с React 17. Но у новых версий проблемы совместимости не будет. На практике это не вызовет затруднений, так как React Native for Web и так должен был обновляться, чтобы не терять совместимость после изменений React.

Кроме того, мы удалили вспомогательные методы ReactTestUtils.SimulateNative . Они не документировались, их названия не соответствовали их функциям, и они не соответствовали изменениям в системе событий. Если вам нужен надёжный способ использовать нативные браузерные события в тестах, обратите внимание на React Testing Library .

Установка

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

Чтобы установить предварительную версию React 17 из npm, используйте команду:

install react@17.0.0-rc.0 react-dom@17.0.0-rc.0 

Для установки из Yarn используйте команду:

Также через CDN доступны UMD-сборки:

 crossorigin src="https://unpkg.com/react@17.0.0-rc.0/umd/react.production.min.js">  crossorigin src="https://unpkg.com/react-dom@17.0.0-rc.0/umd/react-dom.production.min.js"> 

Адаптированный перевод статьи React v17.0 Release Candidate: No New Features by Dan Abramov and Rachel Nabors.

React 17. Разработка веб-приложений на JavaScript

Дронов В. А.
Д75 React 17. Разработка веб-приложений на JavaScript. — СПб.:

БХВ-Петербург, 2022. — 384 с.: ил. — (Профессиональное программирование)

Книга посвящена программированию веб-приложений на языке JavaScript
с применением популярного веб-фреймворка React 17. Дается вводный курс, на-
глядно, по шагам описывающий разработку несложного веб-приложения — списка
запланированных дел. Описываются базовые инструменты: создание и настройка
React-проекта, написание компонентов, язык JSX, передача данных между компо-
нентами и создание веб-форм. Рассматриваются полезные дополнительные биб-
лиотеки: React Router (навигация), Redux, React Redux и Redux Toolkit (централи-
зованное хранилище данных), Formik (быстрая разработка веб-форм), Yup (валида-
ция), React Reveal (анимационные эффекты) и др. Рассказывается о разделении
кода, обработке ошибок, средствах отладки, публикации готового веб-приложения
и рендеринге на стороне сервера.

Электронный архив на сайте издательства содержит код описанного в книге
веб-приложения и другие полезные файлы.

УДК 004.738.5+004.43
ББК 32.973.26-018.2

Группа подготовки издания:

Руководитель проекта Евгений Рыбаков
Зав. редакцией Людмила Гауль
Редактор Григорий Добин
Компьютерная верстка Ольги Сергиенко
Дизайн серии Инны Тачиной
Оформление обложки Зои Канторович

«БХВ-Петербург», 191036, Санкт-Петербург, Гончарная ул., 20.

ISBN 978-5-9775-9683-1 © ООО «БХВ», 2022
© Оформление. ООО «БХВ-Петербург», 2022

Веб-сайты третьего поколения. Фронтенды и бэкенды . 11
Проблемы с программированием фронтендов. 12
Клиентские веб-фреймворки решат все проблемы. 12
Веб-фреймворк React — почему именно он. 13
Что содержится в этой книге? . 13
Необходимые знания и навыки . 14
Использованное ПО. 14
Типографские соглашения. 15

ЧАСТЬ I. СОЗДАНИЕ ПРОСТЕЙШЕГО REACT-ПРИЛОЖЕНИЯ . 17

Глава 1. Список планируемых дел . 18

1.1. Создание проекта todos . 18
Теория. 18
Практика . 18

1.2. Запуск и остановка проекта . 19
1.3. Введение в компоненты. JSX. 21

Теория. 21
Практика . 22
1.4. Вывод компонентов. Пропы и спуск данных . 27
Теория. 27
Практика . 27
1.5. Подъем данных и обработка событий. 31
Теория. 31
Практика . 32
1.6. Состояние компонента . 34
Теория. 34
Практика . 34
1.7. Работа с веб-формами . 37
1.8. Навигация. Маршрутизатор, маршрут и коммутатор. 42
Теория. 42
Практика . 43

1.9. Параметризованные маршруты . 48
Теория. 48
Практика . 49

1.10. Перенаправление . 52

Глава 2. Список планируемых дел 2.0 . 54

2.1. Создание базы данных Google Firebase и подготовка приложения к работе с ней. 54
2.2. Регистрация новых пользователей . 63
2.3. Вход и выход. 70
2.4. Хранение данных в базе Google Firebase. 73

Теория. 73
Практика . 74
2.5. Разграничение доступа в стиле React. 80
2.6. Валидация и вывод сообщений об ошибках в стиле React . 81
Теория. 81
Практика . 82

ЧАСТЬ II. БАЗОВЫЕ ИНСТРУМЕНТЫ . 87

Глава 3. Проект React-приложения. 88

3.1. Создание React-проекта . 88
3.2. Структура React-проекта. 89
3.3. Базовые файлы проекта. 92

3.3.1. Веб-страница приложения . 92
3.3.2. Стартовый модуль . 94
3.3.3. Таблица стилей приложения. 95

3.3.3.1. Сброс стилей . 95
3.3.3.2. Использование таблиц стилей SASS. 96
3.4. Запуск и остановка выполнения проекта. 96
3.4.1. Отслеживание кода. 97
3.4.2. Использование HTTPS при отладке. 98
3.5. Выявление ошибок . 98
3.6. Настройка проекта. Переменные окружения . 100
3.6.1. Задание переменных окружения. Файлы окружения . 101
3.6.2. Использование переменных окружения в программном коде. 102
3.6.3. Переменные окружения, поддерживаемые React . 102
3.6.4. Создание своих переменных окружения . 105

Глава 4. JSX. 106

4.1. Основы синтаксиса JSX . 106
4.1.1. Указание типа выводимого элемента во время выполнения . 109

4.2. Вывод значений . 110
4.3. Задание встроенных стилей CSS . 111
4.4. Условный вывод . 112
4.5. Вывод последовательностей. 113

Глава 5. Компоненты-классы. 115

5.1. Реализация компонентов-классов . 115

5.2. Рендеринг компонентов-классов. Фрагменты. 116
5.2.1. Разделение кода, выполняющего рендеринг. 118
5.2.2. Предотвращение рендеринга . 120

5.3. Пропы компонентов-классов . 120
5.4. Состояние компонентов-классов. 122
5.5. Вывод потомков компонентов-классов . 125

5.5.1. Компоненты, выводящие потомки в разных местах. Слоты. 126
5.5.2. Инструменты для работы с коллекцией потомков . 128
5.6. Жизненный цикл компонента-класса. Волшебные методы . 129
5.7. Принудительное обновление компонента . 134
5.8. Порталы . 134
5.9. Управление элементами веб-страниц. Рефы . 135
5.9.1. Объектные рефы . 135
5.9.2. Функциональные рефы . 136
5.10. Повышение производительности компонентов-классов. Лишние обновления

и их устранение. 137
5.10.1. Явное подавление лишних обновлений . 138
5.10.2. Создание чистых компонентов. 139
5.11. Оформление компонентов. Таблицы стилей компонентов. 140
5.12. Использование внедренных элементов в компонентах. 141

Глава 6. Компоненты-функции . 143

6.1. Реализация компонентов-функций. 143
6.2. Пропы компонентов-функций . 144
6.3. Состояние компонентов-функций . 145
6.4. Жизненный цикл компонента-функции. Хуки . 147

6.4.1. Разработка своих хуков. 149
6.5. Рефы в компонентах-функциях . 150
6.6. Повышение производительности компонентов-функций. Мемоизация. 151

6.6.1. Мемоизация компонентов-функций. 151
6.6.2. Мемоизация результатов вычислений . 152
6.6.3. Мемоизация функций, передаваемых потомкам . 153

Глава 7. Обработка событий. 155

7.1. Написание обработчиков событий . 155
7.2. Привязка обработчиков к событиям . 158

7.2.1. Передача параметров обработчикам событий . 159
7.3. События, поддерживаемые React. Класс события React . 159
7.4. Фазы событий в React. 161

Глава 8. Взаимодействие между компонентами . 163

8.1. Передача данных . 163
8.1.1. Спуск данных . 163
8.1.1.1. Спуск данных посредством пропов. Простой и сквозной спуск . 163
8.1.1.2. Спуск данных посредством контекстов. 165
8.1.2. Подъем данных . 170

8.2. Передача функциональности. Рендер-пропы . 171
8.3. Передача (перенаправление) рефов . 173

Глава 9. Работа с веб-формами и элементами управления . 175

9.1. Работа с веб-формами . 175
9.2. Работа с элементами управления . 176

9.2.1. Неконтролируемые элементы управления . 176
9.2.1.1. Пассивные элементы управления. 176
9.2.1.2. Активные элементы управления . 177

9.2.2. Контролируемые элементы управления . 179
9.3. Валидация заносимых данных. 181

Глава 10. Компоненты высшего порядка . 182

10.1. Компонент высшего порядка, пример 1 . 182
10.2. Компонент высшего порядка, пример 2 . 184

ЧАСТЬ III. ДОПОЛНИТЕЛЬНЫЕ БИБЛИОТЕКИ
И РАСШИРЕННЫЕ ИНСТРУМЕНТЫ. 189

Глава 11. Библиотека PropTypes: контроль типов значений из пропов. 190

11.1. Указание допустимых типов значений. Валидаторы. 190
11.2. Встроенные валидаторы PropTypes . 191
11.3. Создание своих валидаторов . 196

Глава 12. Библиотека React Router: навигация. 198

12.1. Основные принципы и понятия React Router . 198
12.2. Маршрут . 200

12.2.1. Вывод сообщения об ошибке 404 . 200
12.3. Коммутатор . 201
12.4. Маршрутизаторы . 201

12.4.1. Компонент маршрутизатора HashRouter. 201
12.4.2. Компонент маршрутизатора BrowserRouter. 203
12.5. Передача данных в составе путей. URL-параметры . 204
12.6. Гиперссылки React Router. 205
12.6.1. Компонент гиперссылки Link . 205
12.6.2. Компонент гиперссылки NavLink. 206
12.7. Перенаправление . 207
12.7.1. Использование компонента Navigate . 207
12.7.2. Использование хука useNavigate(). 208
12.7.3. Перемещение по истории веб-обозревателя . 209
12.8. Местоположение и его использование . 210
12.9. Многоуровневая навигация . 210
12.10. Особые случаи применения React Router . 214
12.10.1. Использование нескольких коммутаторов . 214
12.10.2. Проверка пути. 214

Глава 13. Библиотека Redux: централизованное хранение состояния,
часть 1. 216

13.1. Библиотека Redux . 216
13.1.1. Воздействия. 217
13.1.2. Преобразователь . 218
13.1.3. Хранилище . 219

13.1.4. Селекторы . 221
13.1.5. Получение данных из хранилища . 221
13.1.6. Отправка воздействий . 222
13.1.7. Регистрация слушателей . 223
13.1.8. Создатели воздействий. 225
13.1.9. Отправители воздействий . 225
13.1.10. Специфические случаи применения Redux . 227

13.1.10.1. Составные преобразователи . 227
13.1.10.2. Замена преобразователя. 229
13.1.10.3. Мемоизация селекторов. Библиотека Reselect. 229
13.2. Выполнение действий с внешними данными. 231
13.2.1. Использование посредников Redux . 231
13.2.2. Использование переходников. Библиотека Redux Thunk. 236

Глава 14. Библиотека Redux: централизованное хранение состояния,
часть 2. 238

14.1. Связывание React-компонентов с хранилищем Redux. Библиотека React Redux . 238
14.1.1. Предоставление хранилища компонентам. Провайдер хранилища . 238
14.1.2. Доступ к хранилищу посредством функции connect(). 239
14.1.2.1. Функция connect(), параметр № 1: получатель данных. 240
14.1.2.2. Функция connect(), параметр № 2: брокер воздействий. 241
14.1.2.3. Функция connect(), параметр № 3: составитель пропов . 243
14.1.2.4. Функция connect(), параметр № 4: настройки. 244
14.1.3. Доступ к хранилищу посредством функции connectAdvanced() . 246
14.1.4. Доступ к хранилищу посредством хуков. 248
14.1.4.1. Получение данных из хранилища . 248
14.1.4.2. Управление данными в хранилище. 250
14.1.4.3. Получение доступа к самому хранилищу. 251
14.1.4.4. Работа с хранилищем, предоставляемым через пользовательский контекст . 251

14.2. Упрощение создания хранилища. Библиотека Redux Toolkit. 252
14.2.1. Упрощение формирования создателей воздействий . 252
14.2.2. Упрощение создания преобразователя . 254
14.2.2.1. Функция createReducer(): первый формат вызова . 254
14.2.2.2. Функция createReducer(): второй формат вызова. 257
14.2.3. Упрощение создания хранилища . 259
14.2.4. Упрощение создания преобразователей срезов . 261
14.2.4.1. Допустимые и недопустимые типы данных в воздействиях. 264
14.2.5. Упрощение создания переходников. 264
14.2.5.1. Создание переходников . 264
14.2.5.2. Создание обработчиков операций. 267
14.2.5.3. Запуск переходников. 269
14.2.5.4. Переходники, возвращающие результат . 269
14.2.5.5. Обработка ошибок в переходниках . 270
14.2.5.6. Прерывание выполнения операций. 271
14.2.6. Создание мемоизированных селекторов . 272

Глава 15. Библиотека Formik: создание веб-форм . 273

15.1. Быстрое создание веб-форм. 273
15.1.1. Компонент Formik: построитель веб-форм . 273

15.1.2. Компонент Form: веб-форма . 275
15.1.3. Компонент Field: элемент управления. 275

15.1.3.1. Вывод флажков, переключателей, списков и полей выбора файлов . 276
15.1.4. Обработка занесенных данных. 278
15.1.5. Валидация данных . 279
15.1.6. Ввод данных в массивы и объекты . 283
15.2. Создание более сложных веб-форм . 284
15.3. Создание своих элементов управления. 289
15.4. Сброс веб-форм. 290
15.5. Массивы элементов управления. 291

Глава 16. Библиотека Yup: валидация данных . 294

16.1. Написание правил валидации. Схемы. 294
16.1.1. Правила, применимые ко всем типам . 296
16.1.2. Правила валидации строк . 296
16.1.3. Правила валидации чисел . 297
16.1.4. Правила валидации логических величин. 298
16.1.5. Правила валидации временны´ х отметок. 298
16.1.6. Правила валидации массивов . 299
16.1.7. Правила валидации объектов. 300

16.2. Валидация данных . 301
16.2.1. Использование только инструментов Yup. 301
16.2.2. Использование Yup совместно с Formik. 302

Глава 17. Библиотека React Reveal: анимация. 303

17.1. Анимационные эффекты. 303
17.1.1. Компоненты, реализующие анимационные эффекты . 303
17.1.2. Общие параметры анимационных эффектов . 306
17.1.3. Анимирование нескольких элементов (компонентов) . 308
17.1.4. Программное управление выводом анимируемого содержимого. 308

17.2. Специальные эффекты . 310
17.3. Преобразование произвольного React-компонента в анимированный . 311

Глава 18. Прочие полезные библиотеки. 313

18.1. Библиотека React Window: вывод больших перечней. 313
18.1.1. Компонент FixedSizeList: вывод списков с пунктами одинакового размера . 313
18.1.2. Компонент VariableSizeList: вывод списков с пунктами разного размера. 318
18.1.3. Компонент FixedSizeGrid: вывод таблиц с ячейками одинаковых размеров . 318
18.1.4. Компонент VariableSizeGrid: вывод таблиц с ячейками разных размеров. 322

18.2. Библиотека React Document Title: вывод названия веб-страницы. 324

Глава 19. Разделение кода и загрузка по запросу . 326

19.1. Загрузка по запросу средствами JavaScript . 326
19.2. Загрузка по запросу средствами React . 327

Глава 20. Обработка ошибок . 329

20.1. Обработка ошибок в обычном программном коде. 329
20.2. Обработка ошибок в коде содержимого. Предохранители. 330

Глава 21. Расширенные средства отладки. 332

21.1. Строгий режим. 332
21.2. Настройка отладчика, встроенного в Visual Studio Code . 333
21.3. Расширение React Developer Tools. 334

21.3.1. Сведения о компонентах . 334
21.3.2. Профилировщик . 337
21.3.3. Настройка расширения. 341
21.4. Расширение Redux DevTools . 344
21.4.1. Подготовка проекта к работе с Redux DevTools . 344
21.4.2. Работа с Redux DevTools. 344
21.4.3. Настройка расширения Redux DevTools. 349
21.5. Получение метрик Web Vitals. 350
21.6. Встроенный профилировщик React . 351

Глава 22. Публикация веб-приложения . 353

22.1. Подготовка веб-приложения к публикации. 353
22.2. Создание эксплуатационной редакции веб-приложения. 354
22.3. Публикация веб-приложения. 356

22.3.1. Публикация на мощностях разработчика . 356
22.3.1.1. Публикация с помощью Apache HTTP Server. 356
22.3.1.2. Публикация с помощью веб-сервера serve. 356

22.3.2. Публикация на сторонних мощностях. 357
22.4. Выброс React-проекта . 357

Глава 23. Рендеринг на стороне сервера. 359

23.1. Базовая реализация рендеринга на стороне сервера. 359
23.1.1. Написание сервера. 360
23.1.1.1. Сервер: стартовый модуль. 360
23.1.1.2. Сервер: основной модуль. 361
23.1.2. Подготовка веб-приложения. 363
23.1.3. Запуск сервера. 364

23.2. Навигация на стороне сервера. Маршрутизатор StaticRouter. 364
23.3. Особенности использования дополнительных библиотек . 366

23.3.1. React Reveal. 366
23.3.2. React Document Title . 366

Глава 24. Добавление React к существующему веб-сайту . 367

24.1. Добавление веб-страницам поддержки React. 367
24.1.1. Добавление React Router . 368

24.2. Написание React-компонентов . 369
24.3. Вывод содержимого React . 370
24.4. Другие полезные инструменты для работы с содержимым React. 371
24.5. Использование JSX. Клиентская редакция Babel . 372
24.6. Публикация веб-сайтов с поддержкой React . 373

Приложение. Описание электронного архива. 377

Предметный указатель . 378

Веб-сайты первого поколения состояли из обычных статических страниц. Они мог-
ли лишь показывать посетителям какие-либо тексты, картинки и позволяли загру-
жать файлы. Оставлять на них отзывы и, тем паче, выкладывать на них свои мате-
риалы посетители возможности не имели.
Сайты второго поколения представляли собой наборы программ, выполняющихся
на стороне сервера и генерирующих обычные страницы, которые отсылались посе-
тителям. Такие сайты могли получать от посетителей какие-либо данные (напри-
мер, отзывы или новые статьи для публикации), записывать их в базы данных и
позднее выдавать другим посетителям.

Веб-сайты третьего поколения.
Фронтенды и бэкенды

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

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

Нередко фронтенд содержит одну-единственную веб-страницу, на которой про-
граммно выводится та или иная часть интерфейса приложения (экран). Такие веб-
приложения носят название одностраничных.
В одностраничных приложениях замечательно все! За единственным исключени-
ем — их фронтенды чрезвычайно сложно программировать.

Проблемы с программированием фронтендов

Таковых две:
описать интерфейс приложения (желательно на языке, максимально приближен-
ном к HTML, — для упрощения разработки и сопровождения);
обновить интерфейс при изменении подлежащих выводу данных (желательно
наиболее оптимально — лишь ту часть интерфейса, в которой выводятся изме-
нившиеся данные).

Можно присвоить HTML-код, описывающий интерфейс фронтенда, свойству
innerHTML какого-либо элемента страницы. Однако такой HTML-код плохо читает-
ся, в нем нетрудно допустить ошибку, его вывод выполняется весьма медленно
(поскольку веб-обозревателю приходится проводить разбор HTML-кода), и возни-
кают трудности с оптимальным обновлением.
Можно сконструировать интерфейс в виде набора объектов DOM, применив мето-
ды createElement(), createTextNode(), appendElement() и т. п. Тогда вывод будет
выполнен быстрее, а трудности с оптимальным обновлением в некоторой степени
устранятся. Однако получившийся код громоздок и тоже плохо читается.
Есть ли средство устранить эти проблемы? Разумеется, да!

Клиентские веб-фреймворки
решат все проблемы

Фреймворк — это программная библиотека, предоставляющая своего рода каркас
какой-либо функциональности. Клиентский веб-фреймворк — это библиотека, пре-
доставляющая каркас фронтенда.
Клиентский веб-фреймворк:

позволяет описать интерфейс приложения:
• либо на языке, очень похожем на HTML;
• либо на обычном HTML с вкраплениями простого шаблонного макроязыка;
самостоятельно, без какого бы то ни было участия программиста и наиболее оп-
тимально — обновит интерфейс при изменении выводимых данных.
Веб-фреймворков существует довольно много: Angular, Vue.js, Backbone, Ember,
Tonic и др. Но самый популярный из них, безусловно, React.

Веб-фреймворк React — почему именно он?

Все потому, что React:

не требует от разработчика изучать никаких дополнительных языков програм-
мирования.

Для описания интерфейса применяется язык JSX, который очень похож на
HTML, «разбавленный» вставками обычного JavaScript;

не вносит никаких дополнительных сложностей и ограничений.

Пишите, как вам удобно, — React покладист;

Другие фреймворки «тормозят» — React реагирует!

Что и неудивительно — ведь React изначально был разработан в корпорации
Facebook и использовался для вывода страниц одноименной социальной сети.
Страниц, чрезвычайно перегруженных сложной разметкой, текстом и графикой;

имеет разветвленную инфраструктуру поддержки:

• множество удобных дополнительных библиотек, расширяющих его функ-
циональность;

• множество сообществ разработчиков, всегда готовых прийти на помощь но-
вичку.

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

А количество свободных вакансий React-программистов год от году не уменьшает-
ся. Вакансий, надо сказать, весьма высокооплачиваемых.

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

Что содержится в этой книге?

Для новичков — вводный курс с практическим упражнением.

. в котором подробно, доходчиво, по шагам описывается программирование
вполне функционального приложения — списка планируемых дел;

максимально полное описание веб-фреймворка React.

Рассказ о компонентах и их разработке, языке JSX, обработке событий, передаче
данных между компонентами, программировании веб-форм, а также создании и
настройке React-проектов;

максимально полное описание дополнительных библиотек, которые обязательно
пригодятся React-программистам.

В их число входят: React Router (навигация), Redux, React Redux и Redux Toolkit
(централизованное хранение данных), Formik (разработка веб-форм), React
Reveal (анимация) и др.;

рассказ об инструментах для отладки и выявления ошибок;

рассмотрение процесса публикации готового веб-приложения и рендеринга на
стороне сервера;

и все это — кратко, доходчиво, на многочисленных примерах.

А чего в этой книге точно нет — так это многословных рассуждений ни о чем и
прочей «воды».

ЭЛЕКТРОННЫЙ АРХИВ
Сопровождающий книгу электронный архив содержит программный код учебного при-
ложения списка запланированных дел, рассматриваемого во вводном курсе. Его можно
скачать с FTP-сервера издательства «БХВ» по ссылке ftp://ftp.bhv.ru/9785977596831.zip,
а также со страницы книги на сайте https://bhv.ru (см. приложение).

Необходимые знания и навыки

Знание HTML, CSS и современных версий JavaScript;
навыки веб-разработки (хотя бы базовые);
знакомство с Node.js (хотя бы поверхностное);
знание баз данных (хотя бы поверхностное).

Таблица. П1. Версии ПО, использованные автором в процессе написания книги

Название Версия Название Версия
Node.js create-react-app 4.0.3
16.5.0,
React 64-разрядная редакция Bulma 0.9.3
React Router Google Firebase SDK 9.1.3
PropTypes 17.0.2 Redux 4.1.1
Reselect 6.0.2 Redux Thunk 2.3.0
React Redux 15.7.2 Redux Toolkit 1.6.2
Formik 4.1.3 Yup 0.32.11
React Reveal 7.2.5 React Window 1.8.6
React Document Title 2.2.9 Visual Studio Code 1.62.2
React Developer Tools 1.2.2 Redux DevTools 2.17.2
serve 2.0.3 ignore-styles 5.0.1
@babel/register 4.21.0 express 4.17.1
12.0.1
7.16.0

Автор работал в среде русской 64-разрядной редакции Microsoft Windows 10
со всеми установленными обновлениями.

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

в угловые скобки (<>) заключаются наименования различных значений, которые
дополнительно выделяются курсивом. В реальный код, разумеется, должны
быть подставлены конкретные значения. Например:

Здесь вместо подстрок содержимое компонента и элемент страницы должны быть
подставлены реальные данные — соответственно, содержимое компонента и
элемент страницы;

в квадратные скобки ([]) заключаются необязательные фрагменты кода. Напри-
мер:

Здесь параметр @ может указываться, но может и отсутствовать (а пара-
метр имя проекта обязателен к указанию);

необязательные параметры функций и методов, имеющие значения по умолчанию,
указываются в формате:

Здесь второй, необязательный, параметр метода setState() имеет значение по
умолчанию undefined;

вертикальной чертой (|) разделяются различные варианты языковой конструк-
ции, из которых следует указать лишь какой-то один. Пример:

Здесь следует поставить либо начальное значение, либо функцию, выдающую на-
чальное значение;
слишком длинные, не помещающиеся на одной строке языковые конструкции
автор разрывал на несколько строк и в местах разрывов ставил знак . Напри-
мер:

Приведенный код разбит на две строки, но должен быть набран в одну. Сим-
вол при этом нужно удалить;

троеточием (. . .) помечены фрагменты, пропущенные ради сокращения объе-
ма кода. Пример:

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

constructor(props) super(props);
this.data = initialData;
this.setDone = this.setDone.bind(this);

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

Todos

/>

Заголовок первого уровня (тег ) следует удалить.

Глава 1. Список планируемых дел
Глава 2. Список планируемых дел 2.0

Список планируемых дел

Изучать React лучше на конкретном примере. В этой главе мы начнем программи-
ровать простое веб-приложение — список планируемых дел. Оно позволит созда-
вать произвольное количество планируемых дел, выводить их перечень в порядке
создания, помечать дела как выполненные и удалять их. Сведения о планируемом
деле включат в себя обязательный заголовок, необязательные примечание и графи-
ческую иллюстрацию (в качестве которой можно указать, скажем, снимок товара,
который следует купить), а также автоматически заносимые дату и время создания.

1.1. Создание проекта todos

Первое, что необходимо сделать, — создать проект нового React-приложения. Про-
ект — это совокупность всех файлов, хранящих программный код приложения.
Можно даже сказать, что проект — это и есть разрабатываемое приложение (по-
этому программисты часто говорят не «запустить приложение», а «запустить про-
ект»).
Каждый проект хранится в отдельной папке (папке проекта), местоположение ко-
торой в файловой системе компьютера может быть произвольным. Проект имеет
имя, совпадающее с именем этой папки.

Создадим проект нашего приложения, дав ему имя todo (сделать). А поскольку
в главе 2 мы превратим его в многопользовательское, добавим в конце «s»: todos.
1. Установим на компьютер программную платформу Node.js версии 10.16 или бо-

лее новой.
Под управлением платформы Node.js исполняются все инструментальные ути-
литы, входящие в состав React-проекта. Дистрибутив этой платформы можно
найти на странице https://nodejs.org/en/.

Глава 1. Список планируемых дел 19

2. Откроем командную строку и в ней выполним переход в папку, в которой будет
находиться папка создаваемого проекта.

Например, если планируется поместить новый проект в папке c:\projects\react,
следует подать в командной строке следующие команды:

c:
cd c:\projects\react

3. Запустим создание нового проекта todos, набрав в командной строке команду:

npx create-react-app todos

Утилита npx, входящая в комплект поставки платформы Node.js, служит для за-
пуска всевозможных программ, написанных под эту платформу, непосредствен-
но из интернет-репозитория Node.js, без необходимости их предварительной
установки на локальный диск. При запуске этой утилиты первым параметром
указывается имя запускаемой программы, а вторым и последующими — пара-
метры, передаваемые запускаемой программе.

В нашем случае npx загрузит и запустит инструментальную утилиту create-react-
app (ее имя задано первым параметром), посредством которой будет создан но-
вый проект React, и передаст этой утилите при запуске имя создаваемого проек-
та — todos (задано вторым параметром).

После запуска npx выведет предупреждение о необходимости загрузить из репо-
зитория Node.js программу create-react-app:

Need to install the following packages:
create-react-app

Ok to proceed? (y)

4. Ответим положительно на появившееся предупреждение, последовательно на-
жав клавиши (от англ. «yes») и .

Утилита npx сохраняет все загруженные программы на локальном диске. При
последующем запуске этих программ будут запущены их локальные копии —
для повышения производительности.

В процессе установки create-react-app и создания React-проекта в командной
строке будут выводиться всевозможные сведения о ходе процесса. Как только
проект будет создан, утилита create-react-app выведет список инструментальных
команд, применяемых в процессе отладки проекта (мы рассмотрим их позже),
и вернет управление командной строке.

Все, новый React-проект todos создан. Можете запустить Проводник, открыть в нем
папку созданного проекта и посмотреть на ее содержимое.

1.2. Запуск и остановка проекта

Вновь созданный React-проект «пуст», т. е. не содержит никакой полезной логики.
Однако он вполне функционален, и его можно запустить на выполнение. Давайте
так и сделаем.

20 Часть I. Создание простейшего React-приложения

1. Откроем командную строку и в ней перейдем непосредственно в папку проекта.
Так, если мы в настоящий момент находимся в папке, в которой ранее создали
проект, то для перехода в папку проекта наберем команду:

2. Запустим проект на выполнение, набрав команду:

После этого будет запущен ряд инструментальных программ, входящих в состав
проекта и подготавливающих файлы с исходным кодом приложения к передаче
веб-обозревателю. Это может отнять довольно много времени (порядка мину-
ты), поэтому следует набраться терпения.
Как только файлы с кодом приложения будут соответственно подготовлены, за-
пустится отладочный веб-сервер, также входящий в состав проекта и работаю-
щий через TCP-порт 3000. Далее автоматически откроется веб-обозреватель,
указанный в настройках операционной системы как используемый по умолча-
нию, и выполнит переход по интернет-адресу http://localhost:3000.
В результате мы увидим интерфейс пустого React-приложения, включающий
вращающийся логотип React, призыв разработчику начать, наконец, разработку
и гиперссылку на домашний сайт фреймворка (рис. 1.1).

Рис. 1.1. Интерфейс пустого React-приложения

Этот интерфейс формируется компонентом приложения, изначально присутст-
вующим в любом новом React-проекте. В разд. 1.3 мы познакомимся с компо-
нентами и переделаем компонент приложения под свои нужды.
3. Остановим работу проекта, переключившись в экземпляр командной строки, из
которого ранее запустили его, нажмем комбинацию клавиш + и под-
твердим завершение работы, нажав клавиши и .

НА ЗАМЕТКУ
Все команды, используемые при работе с проектом, — суть NPM-сценарии, записан-
ные в файле манифеста проекта package.json. Так, введя команду npm start, мы тем
самым запустим на выполнение сценарий start.

Глава 1. Список планируемых дел 21

Если вы пользуетесь текстовым редактором Visual Studio Code, то можете запускать
NPM-сценарии непосредственно из его среды. Переключите боковую панель редакто-
ра на Проводник, раскройте секцию Сценарии NPM, наведите курсор мыши на нуж-
ный сценарий и щелкните на появившейся правее кнопке с изображением стрелки,
направленной вправо.

Для завершения работы проекта, запущенного в среде Visual Studio Code, достаточно
закрыть экземпляр терминала, в котором проект был запущен.

1.3. Введение в компоненты. JSX

Любое веб-приложение, написанное с применением React, содержит в своем соста-
ве всего одну веб-страницу (одностраничное веб-приложение). В процессе дейст-
вий пользователя (в частности, навигации) на этой странице программно выводятся
различные экраны — отдельные части пользовательского интерфейса приложения
(их можно рассматривать как аналоги отдельных страниц традиционных много-
страничных сайтов). Например, приложение списка планируемых дел в разные мо-
менты времени будет выводить экран с перечнем всех дел, экран со сведениями
о деле, выбранном пользователем, экран с веб-формой для добавления нового дела
и др.

В предисловии говорилось, что фреймворк React используется для программирова-
ния интерфейсов веб-приложений. Далее приведены основные принципы React.

Интерфейс веб-приложения состоит из взаимосвязанных компонентов.

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

Компоненты, составляющие интерфейс React-приложения, можно разделить на
три типа:

• обычные компоненты — реализуют какой-либо составной элемент страницы
(например, компоненты отдельной позиции перечня дел или кнопки, поме-
чающей дело как выполненное);

• компоненты-экраны — представляют отдельные экраны приложения (на-
пример, компонент перечня дел);

• компонент приложения — «всеобъемлющий» компонент, в котором в про-
цессе навигации по приложению выводится тот или иной экран и который
представляет само это приложение.

Разбиение интерфейса на компоненты дает два преимущества. Во-первых, неза-
висимые компоненты проще писать и отлаживать по отдельности. Во-вторых,

22 Часть I. Создание простейшего React-приложения

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

Компонент может содержать любые элементы страницы: абзацы, заголовки,
списки, таблицы, изображения, веб-формы с элементами управления, аудио- и
видеоролики и др.

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

Компонент, находящийся в составе другого компонента, называется вложен-
ным, или потомком. Компонент, в который вложен рассматриваемый в текущий
момент компонент, является его родителем. А два или более компонента, вло-
женные в один и тот же компонент, носят название соседей.

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

Компонент управляется состоянием. Состояние — это какие-либо данные, ко-
торые хранятся в компоненте, выводятся компонентом на экран и при измене-
нии которых компонент будет автоматически выведен повторно (обновлен).

Сформируем начальный интерфейс нашего веб-приложения, включающий полосу
навигации и элементы разметки. Для оформления используем популярный CSS-
фреймворк Bulma (https://bulma.io/). Он весьма прост в обращении и не требует
написания громоздкого HTML-кода.

Разметку следует формировать в компоненте приложения. Этот компонент фор-
мируется непосредственно при создании проекта утилитой create-react-app
(см. разд. 1.1). Его код хранится в модуле src\App.js (а в файле src\App.css хранится
таблица стилей этого компонента).

Прежде всего надо установить Bulma и импортировать главную таблицу стилей
этого фреймворка. Ее импорт лучше выполнять в модуле src\index.js, который запус-
кается сразу при открытии страницы приложения и запускает это приложение на
выполнение (стартовый модуль).

1. Откроем командную строку, перейдем в папку проекта (если еще не сделали
этого) и запустим установку Bulma подачей команды:

npm install bulma —save

СОВЕТ
Если вы пользуетесь редактором программного кода Visual Studio Code, вместо ко-
мандной строки можете задействовать терминал, встроенный в этот редактор. При
выводе нового экземпляра терминала он уже будет открыт в папке проекта (разумеет-
ся, если вы предварительно открыли эту папку в самом редакторе).

Глава 1. Список планируемых дел 23

В коде модуля src\index.js уже присутствует выражение, импортирующее таблицу
стилей src\index.css, которая формируется при создании проекта и задает началь-
ное оформление для всего приложения.

2. Откроем в текстовом редакторе стартовый модуль src\index.js и заменим выраже-
ние импорта таблицы стилей src\index.css на выражение, импортирующее табли-
цу стилей Bulma из модуля bulma/css/bulma.css:

.
import ‘./index.css’;
import ‘bulma/css/bulma.css’;

Файл src\index.css после этого можно удалить — более он нам не понадобится.

Теперь можно заняться компонентом приложения. Мы заставим его выводить
полосу навигации и разметку. Сам компонент оформим в виде класса (компо-
нент-класс), которому, в соответствии с принятыми в React-программировании
соглашениями, дадим имя App.

Кроме того, занесем в этот компонент начальные данные — массив из двух
запланированных дел, чтобы впоследствии проверить, как работает компонент
перечня задач. Этот массив присвоим свойству data класса компонента. Каждый
элемент массива будет представлять собой простой объект (созданный на осно-
ве класса Object с применением объектной нотации — фигурных скобок1) со
следующими свойствами:

• title — заголовок дела (описывает, что, собственно, нужно сделать);

• desc — необязательное примечание к делу;

• image — графическая иллюстрация в виде data URL или пустая строка, если
иллюстрация отсутствует;

• done — если false, дело еще не выполнено, если true — уже выполнено;

• createdAt — автоматически заносимые дата и время создания дела, представ-
ленные в виде строки;

• key — уникальный идентификатор дела (пригодится в дальнейшем). Будет
представлять собой временну´ю отметку создания, оформленную в виде коли-
чества миллисекунд, которые прошли с полуночи 1 января 1970 года, и также
будет записываться автоматически.

Для простоты пока не будем указывать у создаваемых дел примечания и графи-
ческие иллюстрации.

3. Откроем в текстовом редакторе модуль src\App.js, хранящий код компонента
приложения App, и полностью заменим его код на представленный в листин-
ге 1.1.

1 Иногда такие объекты еще называют служебными.

24 Часть I. Создание простейшего React-приложения

Листинг 1.1. Модуль arc\App.js
import < Component >from ‘react’;

const date1 = new Date(2021, 7, 19, 14, 5);
const date2 = new Date(2021, 7, 19, 15, 23);

const initialData = [ // . 1
< title: 'Изучить React', 2
desc: ‘Да поскорее!’,
image: »,
done: true, // .
createdAt: date1.toLocaleString(),
key: date1.getTime()
>,
< title: 'Написать первое React-приложение',
desc: ‘Список запланированных дел’,
image:»,
done: false,
createdAt: date2.toLocaleString(),
key: date2.getTime()
>

export default class App extends Component < // . 3
constructor(props) < // . 4
super(props); // . 5
this.data = initialData; // . 6
>

render() < // . 7
return ( // . 8

// . 10

// . 14

Todos

); // . 9

Глава 1. Список планируемых дел 25

Поскольку код компонента App полностью переписан, таблица стилей src\App.css,
импортировавшаяся «старым» компонентом и задающая для него оформление,
более не нужна. Ее можно удалить.

Прежде всего, мы объявили массив с двумя запланированными делами и при-
своили его константе initialData (поз. 1 в листинге 1.2). Первое дело пометили
как выполненное (поз. 2) — это позволит нам в дальнейшем протестировать вы-
вод выполненных дел.

Класс компонента React должен быть производным от класса Component, объяв-
ленного в модуле react (поз. 3).

Класс компонента React может иметь конструктор (поз. 4), в котором выполня-
ются какие-либо подготовительные действия. В качестве единственного пара-
метра он принимает простой объект, хранящий пропы (о них мы узнаем
в разд. 1.4). В конструкторе обязательно следует вызвать конструктор базового
класса, передав ему полученный через параметр объект с пропами (поз. 5), иначе
компонент не заработает. В конструкторе нашего компонента App массив с дела-
ми, хранящийся в константе initialData, присваивается свойству data (поз. 6).

Самая важная часть любого компонента-класса — метод render() (поз. 7), кото-
рый выводит компонент на страницу. Он должен возвращать особый объект,
представляющий содержимое компонента: все имеющиеся в нем абзацы, заго-
ловки, списки, таблицы, элементы управления и пр. (поз. 8).

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

• все теги в JSX являются парными. Например, для вставки графического изо-
бражения следует использовать парный тег:

или его сокращенную запись:

• для указания параметров у тегов в JSX используются не атрибуты HTML, а
соответствующие им свойства классов. Так, для указания стилевых классов
должен быть использован не атрибут тега class, а свойство className.

Поскольку мы для удобства разбили JSX-код на несколько строк, то взяли его
в круглые скобки (поз. 8 и 9). Если этого не сделать, компонент не заработает.

Рассмотрим, какие элементы страницы содержит компонент приложения App.
Прежде всего, это корневой тег , заключающий в себе все содержимое
компонента (поз. 10) — таково требование React. В нем содержатся ряд тегов,
к которым посредством особых стилевых классов привязаны стили, содержа-
щиеся в CSS-фреймворке Bulma:

26 Часть I. Создание простейшего React-приложения

• (поз. 11) — со стилевыми классами navbar (задает оформление полосы
навигации) и is-light (светло-серый цвет фона) — сама полоса навигации,
пока практически «пустая»;
блок (поз. 12) — со стилевым классом navbar-brand — обозначение брен-
да, выводящееся в левой части полосы навигации и обычно представляю-
щее собой название приложения.
В этом блоке находится тег (поз. 13) со стилевыми классами
navbar-item (собственно обозначение бренда) и is-uppercase (приведение
текста к верхнему регистру), в котором и выводится наш бренд — слово
«Todos».
Меню навигации (часть полосы навигации, в которой, собственно, выво-
дятся пункты, предназначенные для перехода на различные экраны при-
ложения) мы создадим потом;

• (поз. 14) — со стилевыми классами content (обычное оформление со-
держимого страницы в стиле Bulma), px-6 (большие внутренние отступы сле-
ва и справа) и mt-6 (большой внешний отступ сверху) — контейнер для выво-
да содержимого экранов. Изначально в нем присутствует заголовок «Todos»,
позже мы заменим его на компонент перечня дел.

Мы только что написали наш первый компонент React! И можем прямо сейчас про-
верить его в действии. Сохраним все исправленные файлы, запустим проект (как
это сделать, было рассказано в разд. 1.2) и посмотрим, правильно ли он выводится
(рис. 1.2).

Рис. 1.2. Полоса навигации и тестовый заголовок

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

СОВЕТ
Если вы пользуетесь редактором Visual Studio Code, установите расширение Babel
JavaScript. Оно выполняет синтаксическую подсветку специфических конструкций язы-
ка JSX, равно как и всех нововведений, появившихся в последних версиях JavaScript,
благодаря чему повышается удобство работы.

Глава 1. Список планируемых дел 27

Веб-обозреватели не поддерживают JSX, поэтому JSX-код перед исполнением преоб-
разуется (транслируется) в обычный JavaScript. Это выполняет популярная програм-
ма-транслятор Babel, входящая в состав проекта React. Помимо того, она преобра-
зует код, написанный с использованием последних нововведений в JavaScript (напри-
мер, нового синтаксиса объявления классов), которые поддерживаются только
самыми современными веб-обозревателями, в более «старый» и более совместимый.

Другая инструментальная программа из состава React-проекта — сборщик Webpack —
собирает программный код из всех файлов в один большой массив — связку, или
бандл1. Это делается для ускорения загрузки, поскольку один большой массив кода
загружается значительно быстрее, чем несколько десятков мелких файлов.

Следующий шаг — программирование компонента, выводящего перечень задач.
Мы поместим его в компонент приложения, сделав потомком последнего. В ре-
зультате компонент приложения автоматически выведет компонент перечня, пред-
варительно передав ему массив со списком задач.

1.4. Вывод компонентов. Пропы и спуск данных

В разд. 1.3 говорилось, что компоненты могут включать в состав своего содержи-
мого, наряду с обычными HTML-тегами, другие компоненты. Более того, сами раз-
работчики фреймворка React настоятельно рекомендуют коллегам по возможности
дробить содержимое сложных компонентов на более простые компоненты — для
упрощения программирования и сопровождения.

Компонент-родитель при выводе компонента-потомка может передать ему произ-
вольные данные — пропы. Каждый проп способен хранить одно значение и должен
иметь уникальное имя, по которому компонент-потомок сможет обратиться к про-
пу, чтобы извлечь переданное значение. Передача данных подобного рода —
«вниз», или «вглубь» компонента — называется спуском.

Напишем компонент TodoList, выводящий перечень запланированных дел в виде
таблицы. Она будет содержать три столбца: заголовок очередного дела и кнопки
Пометить как выполненное и Удалить. У выполненных дел заголовок будет вы-
водиться зачеркнутым, а кнопка Пометить как выполненное станет недоступна.
Реализуем компонент перечня в виде функции (компонент-функция).

Сначала запишем в компонент App код, который выведет компонент TodoList
внутри тега вместо заголовка «Todos».

1. Вставим в метод render() компонента App (модуль src\App.js) код, выводящий
еще не написанный компонент TodoList, а также выражение, импортирующее
его из модуля src\TodoList.js:

1 От англ. bundle — связка.

28 Часть I. Создание простейшего React-приложения

import TodoList from ‘./TodoList’;
.
export default class App extends Component

return (
.

Todos

/>


.

Пока не будем сохранять исправленный модуль — сделаем это позже (объясне-
ния также будут приведены позже).

Чтобы вывести компонент внутри другого компонента, в нужное место JSX-
кода, формирующего содержимое компонента-родителя (он, как мы помним
из разд. 1.3, записывается в методе render()), следует вставить тег, в качестве
имени которого указывается имя выводимого компонента-потомка (тег компо-
нента).

Для вывода компонента TodoList мы использовали тег компонента:

(не забываем, что в JSX все теги — парные).

Чтобы передать массив задач, хранящийся в свойстве data компонента-родителя
App, компоненту-потомку TodoList, мы создали проп с именем list, записав его
непосредственно в теге компонента TodoList, подобно обычному свойству.

Значение пропа list фактически получается в результате выполнения выраже-
ния JavaScript, которое извлекает массив дел из свойства data. А любые выраже-
ния JavaScript, помещаемые в JSX-код, должны быть взяты в фигурные скобки.
Что мы и сделали (а если бы не сделали, проп в качестве значения получил бы
совершенно бесполезную строку ‘this.data’).

2. Создадим модуль src\TodoList.js и запишем в него код компонента TodoList из
листинга 1.2.

Листинг 1.2. Модуль src\TodoList.js

export default function TodoList(props) < // . 1
return ( 2
// . 3

Дела

// .

Список планируемых дел 2.0

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

2.1. Создание базы данных Google Firebase
и подготовка приложения к работе с ней

Google Firebase — это популярная интернет-служба, предназначенная для разра-
ботчиков приложений. В ее состав входят: документная СУБД1, облачное храни-
лище файлов, веб-хостинг для статических сайтов и др. Фактически Firebase позво-
ляет разрабатывать бессерверные клиентские веб-приложения, не требующие напи-
сания отдельного бэкенда.
Firebase предоставляет, помимо ряда платных тарифных планов (различающихся
ценой и объемом предоставляемых услуг), еще и бесплатный. Для начинающих
программистов и разработчиков некоммерческих приложений это наилучший ва-
риант.
Создадим в службе Firebase базу данных todos, в которой будут храниться списки
запланированных дел, и подсистему разграничения доступа с регистрацией пользо-
вателей по адресу электронной почты и паролю. Установим в проекте todos кли-

1 Вообще-то, там имеются две СУБД: Realtime Database и Cloud Firestore. Мы будем использовать
Realtime Database, так как работать с ней проще, а ее возможностей достаточно для нашего простого
приложения.

Глава 2. Список планируемых дел 2.0 55

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

1. Перейдем по интернет-адресу https://firebase.google.com/, чтобы попасть на
«домашний» сайт Google Firebase.

2. Щелкнем на гиперссылке Go to console, расположенной в правом верхнем углу
открывшейся веб-страницы, чтобы попасть на страницу консоли — центра
управления всеми инструментами, предоставляемыми Firebase.

3. Если не сделали этого ранее — выполним вход в интернет-службы Google.

Сначала следует создать новый серверный проект Firebase (не путать с проектом
React-приложения), который станет «вместилищем» для наших базы данных и
подсистемы разграничения доступа.

4. Щелкнем на белой кнопке Create a project, расположенной на открывшейся
странице консоли, чтобы создать новый серверный проект.

5. Занесем в веб-форму, расположенную на следующей странице (рис. 2.1), сле-
дующие данные:

• Project name — имя создаваемого проекта: todos.

Если введенное имя совпадает с именем какого-либо из уже существующих
проектов, созданных другими клиентами Firebase, для достижения уникаль-
ности заданного имени служба добавит к нему набор произвольных симво-

Рис. 2.1. Создание нового проекта Google Firebase, этап 1

56 Часть I. Создание простейшего React-приложения

лов. Сгенерированное таким образом заведомо уникальное имя будет выве-
дено под полем ввода Project name. Так, после ввода автором имени todos,
явно уже «занятого», служба превратила его в todos-c1c79;
• I accept the Firebase terms (может отсутствовать) — установим этот флажок,
соглашаясь с правилами пользования Firebase (прочитать которые можно, пе-
рейдя по гиперссылке Firebase terms, расположенной в надписи к флажку).
6. Нажмем на кнопку Continue для перехода ко второму этапу создания проекта.
Очередная страница (рис. 2.2) порекомендует задействовать в создаваемом про-
екте услугу Google Analytics, которая включает в себя сбор статистики работы
базы данных, анализ действий пользователей и др. На взгляд автора, при ис-
пользовании лишь базы данных и разграничения доступа эта услуга не нужна.
7. Сбросим выключатель Enable Google Analytics for this project, чтобы отказать-
ся от услуги Google Analytics.
8. Нажмем на кнопку Create project, чтобы запустить процесс создания проекта.
Придется подождать около минуты, пока Google создает проект.

Рис. 2.2. Создание нового проекта Google Firebase, этап 2

Глава 2. Список планируемых дел 2.0 57

ВНИМАНИЕ!
Любой вновь созданный серверный проект Google Firebase по умолчанию связывается
с бесплатным тарифным планом Spark.

9. Нажмем на кнопку Continue на следующей странице, чтобы вернуться в кон-
соль.

Будет открыта страница только что созданного проекта.

Теперь необходимо создать и зарегистрировать в только что созданном проекте
серверное веб-приложение, которое станет своего рода представлением нашего
клиентского React-приложения в Firebase.

10. Нажмем на круглую кнопку , чтобы открыть страницу создания серверного
приложения.

11. Занесем в веб-форму сведений о создаваемом приложении (рис. 2.3) следующие
данные:

• App nickname — имя приложения: Todos;

• Also set up Firebase Hosting for this app — сбросим этот флажок, т. к. не со-
бираемся публиковать свое приложение на хостинге Firebase.

Рис. 2.3. Привязка приложения к проекту

12. Нажмем на кнопку Register app, чтобы создать и зарегистрировать в проекте
серверное приложение.

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

58 Часть I. Создание простейшего React-приложения
var firebaseConfig = apiKey: . . .,
authDomain: . . .,
projectId: . . .,
storageBucket: . . .,
messagingSenderId: . . .,
appId: . . .
>;

13. Скопируем этот код в буфер обмена.
14. Создадим в проекте нашего приложения модуль src\firebase.js и сохраним в нем

скопированный ранее код.
При желании можем заменить в этом коде устаревший оператор объявления
переменной var более современным const (автор так и сделал).
15. Нажмем на кнопку Continue to console, чтобы вернуться в консоль.
Теперь можно создать базу данных Realtime Database.

ВНИМАНИЕ!
Бесплатный тарифный план Spark позволяет создать в серверном проекте лишь одну
базу данных.

16. Щелкнем на расположенном в панели навигации слева пункте Realtime
Database, чтобы переключиться в раздел, предназначенный для управления
базой данных.

17. Нажмем на белую кнопку Create Database, чтобы открыть диалог создания
базы данных.
Первая страница (рис. 2.4) этого диалога соответствует первому этапу создания
базы данных — заданию места ее хранения. Автор рекомендует выбрать место
поближе.

Рис. 2.4. Создание базы данных, этап 1

Глава 2. Список планируемых дел 2.0 73

Закончив с реализацией входа и выхода, начнем «учить» приложение работать
с базой данных Google Firebase.

2.4. Хранение данных в базе Google Firebase

СУБД, являющаяся частью службы Firebase, является документной, т. к. хранит
данные в документах, описывающих какие-либо отдельные сущности (например,
дела) и представленных в виде простых объектов JavaScript. Каждый документ со-
держит произвольный набор свойств, которые могут хранить строки, числа, логи-
ческие величины, null, другие документы или коллекции из произвольного числа
других значений, включая документы. В «основании» базы данных должен быть
один документ, называемый корневым, — все остальные значения, документы
и коллекции должны храниться в его свойствах.

Каждый документ, хранящийся в коллекции, должен иметь уникальный идентифи-
катор. Он может как указываться явно при добавлении документа, так и присваи-
ваться самой СУБД, — в последнем случае он представляет собой строку, сформи-
рованную на основе текущих даты и времени. Так что документы в любой коллек-
ции уже выстроены по хронологическому признаку.

Вот пример небольшой базы данных, представленный в виде JSON-кода:

«9bBtqvTbByes7AIZTlWrviPoU1o1» : < // . 2
«todos» : < // . 3
«-Mfrhf9_Y76XrNvXhSo9» : < // . 4
«createdAt» : «19.07.2021, 14:05:00», // . 6
«desc» : «Да поскорее!»,
«done» : true, 5
«image» : «»,
«title» : «Изучить React»
>,
«-Mfrht2wBLBmtza0zETW» : < // .
«createdAt» : «19.07.2021, 15:23:40»,
«desc» : «Список запланированных дел»,
«done» : false,
«image» : «»,
«title» : «Написать первое React-приложение»
>

74 Часть I. Создание простейшего React-приложения

Корневой документ имеет единственное свойство users (поз. 1 в приведенном при-
мере), хранящее коллекцию документов, каждый из которых представляет одного
пользователя приложения. Каждый документ в этой коллекции хранится под
уникальным идентификатором (так, первый документ имеет идентификатор
9bBtqvTbByes7AIZTlWrviPoU1o1 — см. поз. 2) и содержит свойство todos (поз. 3),
в котором находится коллекция документов-дел. Отдельный документ-дело также
имеет уникальный идентификатор (поз. 4 и 5) и набор свойств, хранящих элемен-
тарные значения: строки и логические величины (поз. 6).

Чтобы получить доступ к какой-либо коллекции, отдельному документу или от-
дельному свойству в документе, следует записать указывающий на него путь,
представляющий набор имен свойств и идентификаторов, разделенные слешами.
Так, чтобы получить коллекцию всех дел, созданных пользователем с идентифика-
тором 9bBtqvTbByes7AIZTlWrviPoU1o1, следует записать путь:

Для получения дела с идентификатором -Mfrht2wBLBmtza0zETW — путь:

А для получения описания этого дела — путь:

Реализуем в нашем приложении работу с базой данных Firebase: хранение в ней
списка дел, считывание списка, добавление дела, пометку его как выполненного и
удаление.

Начнем с добавления новых дел. Объявим функцию add(), которая добавит в базу
указанное дело, созданное заданным пользователем:

Функция вернет добавленный документ, представленный простым объектом
JavaScript.

Добавляемые дела будут записываться в коллекцию по пути формата:

1. Добавим в модуль src\api.js объявление функции add():

export async function add(user, deed) const oRef = await push( // .

Глава 3. Проект React-приложения
Глава 4. JSX
Глава 5. Компоненты-классы
Глава 6. Компоненты-функции
Глава 7. Обработка событий
Глава 8. Взаимодействие между компонентами
Глава 9. Работа с веб-формами и элементами управления
Глава 10. Компоненты высшего порядка

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

3.1. Создание React-проекта

Для создания нового React-проекта следует в командной строке перейти в папку,
в которой должна находиться папка создаваемого проекта, и подать команду фор-
мата:

Если версия не указана, будет использована наиболее актуальная версия утилиты
create-react-app.
Пример:

npx create-react-app todos

Пример использования create-react-app версии 4.0.3 — актуальной на момент напи-
сания этой книги:

Если заданная версия утилиты create-react-app еще ни разу не запускалась, утилита
npx выведет предупреждение о необходимости загрузить эту программу из репози-
тория Node.js и установить на компьютер:

Need to install the following packages:
create-react-app

Ok to proceed? (y)

Глава 3. Проект React-приложения 89

На это предупреждение следует ответить положительно, последовательно нажав
клавиши (от англ. «yes») и .

В результате будет создан проект в папке с указанным именем.

Командный ключ —template задает имя шаблона, на основе которого будет создан
проект. Шаблон React-приложения служит своего рода заготовкой для создания
проекта, содержит указания на установку необходимых зависимостей (библиотек,
включая сам React, и инструментальных программ) и начальный программный код
(в частности, стартовый модуль и компонент приложения).

Если ключ —template не указан, проект будет создан на основе базового шаблона
cra-template. Он включает лишь необходимый минимум библиотек и минимали-
стичный компонент приложения, показанный на рис. 1.1.

Другие доступные для указания шаблоны можно найти в репозитории Node.js, об-
ратившись по интернет-адресу https://www.npmjs.com/search?q=cra-template-*.
Они включают всевозможные дополнительные библиотеки (React Router, Redux,
Bootstrap и др.) и дополнительный программный код, реализующий какие-либо ти-
повые операции с использованием этих библиотек.

Далее будет описываться работа с проектом, созданным на основе базового шаблона
cra-template.

3.2. Структура React-проекта

В папке вновь созданного проекта изначально присутствуют следующие папки
и файлы:

public — папка, предназначенная для хранения файлов, которые не должны под-
вергаться никакой обработке перед отправкой веб-обозревателю. Изначально
в ней находятся следующие файлы:

• index.html — единственная веб-страница, на который выводится интерфейс
приложения (страница приложения). В подробностях будет рассмотрена
позже;

• favicon.ico — значок страницы приложения. Представляет собой логотип
React;

• robots.txt — файл с указаниями для поисковых служб, пока что практически
пустой;

• manifest.json — манифест прогрессивного веб-приложения (PWA). Требуется
при программировании PWA;

• logo192.png — значок PWA размерами 192×192 пиксела;

• logo512.png — значок PWA размерами 512×512 пикселов.

Если разрабатываемое приложение не планируется превращать в PWA, фай-
лы manifest.json, logo192.png и logo512.png могут быть удалены. При этом необ-

90 Часть II. Базовые инструменты

ходимо также удалить из HTML-кода страницы приложения index.html ссылки
на файлы manifest.json и logo192.png.

При запуске проекта на выполнение папка public выступает в качестве корневой
папки веб-приложения. Все пути к файлам, присутствующие в интернет-адресах,
отсчитываются от нее;

src — папка, предназначенная для хранения файлов, которые должны обрабаты-
ваться перед отправкой веб-обозревателю. Изначально она хранит файлы:

• index.js — стартовый модуль;

• index.css — таблица стилей приложения. Импортируется в модуле index.js;

• App.js — модуль с кодом компонента приложения;

• App.css — таблица стилей компонента приложения. Импортируется в модуле
App.js;

• logo.svg — логотип React, выводимый компонентом приложения. Импортиру-
ется в модуле App.js;

• App.test.js — тестовый модуль для компонента приложения. Если средства ав-
томатизированного тестирования, устанавливаемые в составе инструмен-
тальных программ, использовать не планируется, может быть удален.

ВНИМАНИЕ!
Автор не будет описывать встроенные в React средства автоматизированного тести-
рования, поскольку не считает их сколь-нибудь полезными.

• reportWebVitals.js — модуль встроенного в React измерителя производительно-
сти приложения.

Если измеритель производительности не нужен, его можно удалить. При
этом также необходимо удалить из модуля index.js выражение, вызывающее
функцию reportWebVitals(), которая импортируется из этого модуля, а также
выражение, импортирующее эту функцию;

• setupTests.js — модуль, инициализирующий средства автоматизированного
тестирования React. Если эти средства использоваться не будут, модуль мо-
жет быть удален;

node_modules — папка с установленными зависимостями (библиотеками, вклю-
чая сам React, и инструментальными программами);

.gitignore — список исключений для системы управления версиями Git. Вклю-
чает, в частности, папки node_modules, build и файлы с именами формата
.env..local;

package.json — манифест проекта Node.js;

package-lock.json — снимок дерева зависимостей Node.js;

README.MD — краткое описание проекта в формате Markdown.

Кроме того, если на компьютере установлена система Git, в папке проекта создает-
ся Git-репозиторий.

Компонент-класс — это компонент React, реализованный в виде класса. Преиму-
щества компонентов-классов перед компонентами-функциями:

возможность хранить произвольные данные в течение всего времени существо-
вания компонента — в свойствах представляющего его объекта;
более развитые инструменты, позволяющие вмешаться в работу компонента для
реализации дополнительной функциональности, — волшебные методы;
возможность создавать рефы, ссылающиеся на компоненты-классы (рефы опи-
саны в разд. 5.9);
возможность управлять компонентами-классами через ссылающиеся на них
рефы, вызывая объявленные в компонентах методы.
Недостатки:
больший объем занимаемой памяти (поскольку экземпляр компонента-класса
является объектом класса, он требует дополнительную память для своего раз-
мещения);
потеря состояния после обновления запущенного приложения.

5.1. Реализация компонентов-классов

Компонент-класс должен быть производным от класса Component из модуля react.
Имя компонента-класса должно начинаться с большой буквы.
В компоненте-классе должны присутствовать, по крайней мере, следующие ме-
тоды:

конструктор — требуется для задания изначального состояния компонента и
выполнения какой-либо инициализации. В качестве единственного параметра он
должен принимать простой объект с пропами, полученными компонентом.
При объявлении конструктора в самом его начале следует вызвать конструктор
базового класса, передав ему полученный ранее объект с пропами, — иначе
компонент не заработает.

116 Часть II. Базовые инструменты

Если компонент не имеет состояния и не инициализируется при создании, кон-
структор объявлять необязательно;
render() — должен возвращать объектную структуру, представляющую содер-
жимое компонента и записанную на языке JSX (см. главу 4).
Вот шаблон, согласно которому объявляются компоненты-классы:

import < Component >from ‘react’;
class SomeComponent extends Component

constructor() super();
// Задание изначального состояния
// Инициализационный код

render() return (
// Содержимое компонента, написанное на языке JSX
);

Статическое свойство displayName позволяет указать отображаемое имя компонен-
та, выводимое в составе сообщений об ошибках в виде строки. Если отображаемое
имя не указано, будет выводиться имя класса компонента.
В классе компонента также можно объявить произвольные свойства и методы.

5.2. Рендеринг компонентов-классов.
Фрагменты

Рендерингом называется вывод компонента на страницу. Рендеринг бывает:
первоначальный, или монтирование, — первое отображение компонента на
странице;
повторный, или обновление, — повторное отображение (перерисовка) ком-
понента, выполняемое после изменения состояния компонента, его пропов или
обновления его родителя.

И первоначальный, и повторный рендеринги выполняет сам React, основываясь на
содержимом компонента, полученном из метода render() его класса.
Метод render() может возвращать:

произвольный тег (например, блок — тег ), вмещающий в себя все содер-
жимое компонента и называемый корневым:

return (

Перечень дел

Глава 5. Компоненты-классы 117

Подобного рода возвращаемый результат реализуется в большинстве случаев;
фрагмент, вмещающий все содержимое компонента.
Фрагментом называется особый компонент, встроенный в React, который не
преобразуется в какие бы то ни было HTML-теги, не выводится на странице и
служит лишь вместилищем для какого-либо содержимого. Фрагмент реализован
в виде класса Fragment из модуля react. Пример:

Перечень дел

.

Поддерживается компактная запись фрагмента (при ее использовании явно им-
портировать класс Fragment необязательно):

return (
<>

Перечень дел

.

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

Фрагменты также могут задействоваться, чтобы объединить часть тегов с какой-
либо целью (например, чтобы указать у них ключ):

У фрагментов, записанных в компактном формате, указать ключ нельзя;

118 Часть II. Базовые инструменты

массив тегов.
При этом не следует забывать, во-первых, разделять отдельные теги в массиве
запятыми, и, во-вторых, указывать у тегов произвольные ключи (поскольку фак-
тически выполняется вывод последовательности, описанный в разд. 4.5).
Пример:

return [
,

,

,

alt=»Иллюстрация» />

Возврат массива тегов также позволяет отказаться от корневого тега, который
может нарушить разметку страницы.

5.2.1. Разделение кода, выполняющего рендеринг

В классе компонента можно объявить другие методы, возвращающие в качестве
результата части содержимого компонента, и вызывать эти методы в нужных мес-
тах метода render(). Это позволит сделать код более наглядным и упростить его
сопровождение.

В листинге 5.1 показан код компонента перечня дел, в котором использован прин-
цип разделения кода, производящего рендеринг.

Листинг 5.1. Пример разделения кода, выполняющего рендеринг
import < Component >from ‘react’;

export default class TodoList extends Component < 1
renderDeedTitle(item) if (item.done) // .
return ;
else
return item.title;
>

Добавление React
к существующему веб-сайту

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

24.1. Добавление веб-страницам
поддержки React

Добавить веб-страницам существующего сайта поддержку React очень просто —
для этого достаточно привязать к ним два веб-сценария, один из которых хранит
код программного ядра фреймворка, а другой — код подсистемы рендеринга на
веб-страницах.
Теги , посредством которых привязываются эти сценарии, можно взять со
страницы: https://ru.reactjs.org/docs/cdn-links.html.
На этапе разработки рекомендуется использовать редакции сценариев, предназна-
ченные для разработки. Их код отформатирован для наилучшей читаемости. Сце-
нарии с редакцией, предназначенной для разработки, можно отличить по слову
development, присутствующему в именах их файлов.
Пример HTML-кода, привязывающего к странице необходимые сценарии:

368 Часть III. Дополнительные библиотеки и расширенные инструменты

Атрибут без значения crossorigin в тегах необходим для более успешной
обработки ошибок.
После выполнения упомянутых сценариев в памяти будут созданы две переменные:

React — содержащая простой объект со свойствами, хранящими все функции и
классы, которые мы ранее получали из модуля react.
Так, чтобы получить базовый класс компонента Component, достаточно обратить-
ся к одноименному свойству этого объекта:

class SomeComponent extends React.Component

ReactDOM — содержащая простой объект со свойствами, хранящими функции,
которые ранее извлекались из модуля react-dom.
Например, функцию render(), выполняющую вывод содержимого в указанный
элемент страницы и упомянутую в разд. 3.3.2, можно получить из одноименного
свойства этого объекта:

24.1.1. Добавление React Router

Чтобы добавить страницам поддержку библиотеки навигации React Router, следует,
помимо React, привязать к ним три веб-сценария, хранящие код библиотек для дос-
тупа к истории веб-обозревателя, программного ядра React Router и подсистемы
рендеринга этой библиотеки на веб-страницах
Теги , посредством которых привязываются эти сценарии, можно взять
со страницы: https://reactrouter.com/docs/en/v6/getting-started/installation#html-
script-tags.
Пример:

Глава 24. Добавление React к существующему веб-сайту 369

После выполнения этих сценариев в памяти будет создана переменная
ReactRouterDOM, хранящая простой объект со свойствами, содержащими все функ-
ции и классы, которые мы ранее получали из модуля react-router-dom. Например,
чтобы получить классы HashRouter, Routes и Route, достаточно обратиться к одно-
именным свойствам этого объекта:

24.2. Написание React-компонентов

Ранее мы писали код, выводящий содержимое компонентов, на языке JSX, который
Babel при запуске проекта транслировал в обычный JavaScript. Но теперь Babel не
сможет помочь нам в работе, поэтому придется обходиться JavaScript.
Для создания какого-либо элемента содержимого — HTML-тега или компонента —
служит функция createElement() из объекта React:

В качестве типа элемента можно указать строку с именем HTML-тега или компо-
нент: класс или функцию.

Пропы и обработчики события следует указать в виде простого объекта. Имена его
свойств должны совпадать с именами задаваемых пропов и обработчиков событий,
а значения свойств зададут значения пропов и обработчики.
Третьим и последующими параметрами можно указать произвольное количество
потомков создаваемого элемента. Фрагменты текста задаются в виде строк, а
HTML-теги и компоненты — в виде результатов вызовов функции createElement().
Функция возвращает созданный элемент содержимого, готовый к выводу на стра-
ницу.
В листинге 24.1 приведен код компонента спойлера Spoiler, написанного с приме-
нением функции createElement(), — без использования JSX.

Листинг 24.1. Компонент Spoiler, написанный без применения JSX

class Spoiler extends React.Component static defaultProps =

370 Часть III. Дополнительные библиотеки и расширенные инструменты

constructor(props) super(props);
this.state = < isOpened: props.isOpened >;
this.toggle = this.toggle.bind(this);

Для работы этому компоненту требуются стили со стилевыми классами spoiler
(действует на корневой тег), header (на заголовок спойлера) и closed (привязывает-
ся к корневому тегу и сворачивает спойлер). Вы можете написать таблицу стилей,
содержащую подходящие стили, и привязать ее к странице самостоятельно.

24.3. Вывод содержимого React

Для вывода содержимого React на странице сначала следует создать пустой тег,
который послужит контейнером для его размещения. Обычно в качестве контей-
нера применяют блок (тег ). Если контейнер не пуст, его содержимое будет
удалено.
Вывод указанного элемента содержимого в заданный контейнер выполняет функция
render() из объекта ReactDOM:

Элемент содержимого должен быть создан вызовом функции createElement(), опи-
санной в разд. 24.2. Контейнер указывается в виде представляющего его объекта
DOM.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *