React в действии
Қосымшада ыңғайлырақҚосымшаны жүктеуге арналған QRRuStore · Samsung Galaxy Store
Huawei AppGallery · Xiaomi GetApps

автордың кітабын онлайн тегін оқу  React в действии

 

Марк Тиленс Томас
React в действии
2018

Переводчик С. Черников

Технические редакторы Т. Радецкая, Н. Рощина

Литературный редактор Н. Рощина

Художники Н. Гринчик, С. Заматевская

Корректоры О. Андриевич, Е. Павлович

Верстка Г. Блинов

 

Марк Тиленс Томас

React в действии. — СПб.: Питер, 2018.

 

ISBN 978-5-4461-0999-9

© ООО Издательство "Питер", 2018

 

Все права защищены. Никакая часть данной книги не может быть воспроизведена в какой бы то ни было форме без письменного разрешения владельцев авторских прав.

 

Эта книга посвящается моей жене Хейли. Оставайся навсегда…

Предисловие

Когда я стал изучать и применять на практике JavaScript-библиотеку React, сообщество JavaScript только начинало успокаиваться после периода быстрых инноваций и сбоев (читайте: турбулентностей). Библиотека набирала популярность, и я был в восторге от технологичности React, потому что она предлагала реальные перспективы. Ментальная модель казалась солидной, компоненты упрощали создание пользовательских интерфейсов, API был гибким и выразительным, а весь проект казался именно таким, как надо. Утверждения об удобстве использования API библиотеки также способствовали тому, что у меня сложилось о ней хорошее впечатление.

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

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

Библиотека React не только стала очень популярной в Интернете, но и была портирована на другие платформы. Библиотека React Native — порт React для мобильных платформ — также стала важной новинкой. Все это демонстрирует подход React в духе «однажды научившись, писать где угодно». Это представление библио­теки React как платформы означает, что вы не ограничены ее использованием для разработки браузерных приложений.

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

Благодарности

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

Кэтмелл Э. Корпорация гениев. Как управлять командой творческих людей

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

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

Во-первых, я хотел бы поблагодарить свою жену Хейли. Она — моя радость, мой лучший друг, мой творческий партнер. Ей понадобилось колоссальное терпение, пока я работал над этой книгой. Поздние вечера, глубокие ночи и бесконечные разговоры о книге. Супруга — блестящий писатель — помогла мне, когда случился творческий застой. Она ободряла меня, когда казалось, что закончить книгу невозможно. Она всегда постоянна — в любви и в молитве. Она мгновенно успокаивала меня, подбадривала, когда я сомневался в себе, и отмечала со мной радостные моменты. Она была невероятной в течение всего процесса, и я не могу дождаться, когда смогу ответить ей поддержкой и помочь с множеством книг, которые она напишет в будущем. Я безмерно благодарен Хейли.

Хотелось бы поблагодарить и других близких людей за поддержку. У меня невероятная семья. Мать и отец, Эннмари и Митчелл, обнадеживали меня во время написания книги (и в ходе всей моей жизни). Они пообещали прочитать ее от корки до корки, хотя я не буду заставлять их. Братья, Давид и Питер, также поддерживали и поощряли меня. Однако они не давали обещаний, как родители, поэтому я буду читать им ее вслух весь следующий год (или сколько потребуется). Друзья и коллеги также принесли большую пользу, спрашивая: «Уже закончил» — чтобы подтолкнуть меня, и терпели, когда я объяснял принципы работы библиотеки React. Хочу поблагодарить и моих наставников, особенно доктора Диану Павлак Глиэр (Diana Pavlac Glyer), за то, что научили меня думать в верном направлении и записывать свои мысли.

Сотрудники издательства Manning тоже очень помогли мне. Особенная благодарность Марине Майклз (Marina Michaels) — редактору-консультанту по аудитории, Ники Брукнер (Nickie Bruckner) — техническому редактору-консультанту и Герману Фриджерио (German Frigerio) — корректору. Они потратили множество часов на чтение моей книги и помогали мне писать. Без них ее не было бы. Я также хотел бы сказать спасибо Брайану Сойеру (Brian Sawyer) — именно он предложил мне написать эту книгу, и Марьяне Бэйс (Marjan Bace) — за то, что дала такую возможность. Каждый сотрудник издательства Manning стремится помогать людям эффективно получать важные навыки и познавать концепции. Я точно знаю это и буду очень рад и в дальнейшем способствовать образовательной миссии Manning.

О книге

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

Аудитория

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

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

Предполагается, что вы владеете технологическими основами разработки клиентских веб-приложений, пригодится и знание базовых API браузера. Придется иметь дело с API Fetch, чтобы выполнять сетевые запросы, устанавливать и получать файлы cookie, а также работать с пользовательскими событиями (ввод, щелчки кнопкой мыши и т.д.). Кроме того, вы будете активно взаимодействовать с библиотеками (хотя и не слишком много!). Знание основ современных клиентских приложений поможет извлечь максимальную пользу из этой книги.

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

Структура издания

Главы книги разделены на три части.

Часть I «Обзор React» знакомит с библиотекой React. В главе 1 рассматриваются основные принципы ее работы. В ней рассказано о ключевых моментах, на которых базируется React, и показано, как они могут вписаться в процесс разработки. Также мы рассмотрим, что библиотека делает, а чего не делает. Глава 2 демонстрирует принципы работы с кодом. Вы изучите API React и создадите простой блок комментариев с помощью компонентов библиотеки.

Часть II «Компоненты и данные в React» — это погружение в React. Вы увидите, как в ней передаются данные (глава 3). В главе 4 изучите жизненный цикл компонентов и приступите к разработке проекта социального приложения. Над этим проектом будете трудиться и в дальнейшем. В главе 4 рассматривается настройка проекта с помощью исходного кода и объясняется, как работать с ним в остальной части книги. Главы 5–9 погружают вас в глубины библиотеки React. Глава 5 охватывает действия с формами и учит работать с данными и их потоками. В главе 6 на основе проделанного в главе 5 создается более сложный компонент React для отображения карт. Главы 7 и 8 касаются маршрутизации — важной составляющей практически любого современного приложения. Вы создадите роутер с нуля и настроите приложение для поддержки нескольких страниц. В главе 8 продолжите работу с маршрутизацией и интегрируете платформу Firebase, чтобы аутентифицировать пользователей. Глава 9 знакомит с тестированием приложений и компонентов React.

Часть III «Архитектура React-приложений» охватывает более сложные темы и фокусируется прежде всего на том, как перевести ваше приложение на использование библиотеки Redux. В главах 10 и 11 представлена библиотека Redux — решение для управления состоянием. После того как приложение перейдет на Redux, в главе 12 поговорим о рендеринге на стороне сервера. В ней рассматривается также отключение пользовательского роутера для применения React Router. В главе 13 вкратце обсуждается React Native — проект, который позволяет разрабатывать React-приложения на языке JavaScript для мобильных устройств (iOS и Android).

О коде

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

В главе 4 вы займетесь настройкой исходного кода проекта. Все исходные файлы доступны для загрузки на веб-сайте книги по адресу www.manning.com/books/react-in-action и на сайте GitHub по адресу github.com/react-in-action/letters-social, а окончательный результат проекта опубликован по адресу social.react.sh. Каждая глава или группа разделов имеет собственную ветку Git, поэтому вы можете легко перейти к следу­ющей главе или следовать за развитием проекта на протяжении всей книги. Исходный код опубликован и поддерживается на сайте GitHub, поэтому задавайте возникающие вопросы на GitHub или на форуме книги на странице forums.manning.com/forums/react-in-action.

JavaScript-код приложения должен быть отформатирован с помощью инструмента Prettier (github.com/prettier/prettier) с учетом последней спецификации ECMAScript (ES2017 на момент написания книги). Инструмент Prettier учитывает концепции, синтаксис и методы, изложенные в этой спецификации. Проект включает в себя конфигурацию ESLint, но при желании модифицируйте ее как угодно.

Требования к программному и аппаратному обеспечению

Эта книга не имеет строгих требований к аппаратному обеспечению. Можете использовать любой компьютер — физический или виртуальный (например, на сайте c9.io), но я не буду рассматривать несоответствия, вызванные различиями в средах разработки. Если проблемы возникают во время работы с определенными пакетами, их репозитории, а также сайт Stack Overflow (stackoverflow.com) — лучшие помощники в их решении.

Что касается программного обеспечения, приведу несколько требований и рекомендаций.

Сборка проекта предусматривает работу с платформой node.js (nodejs.org), поэтому нужно установить ее последнюю стабильную версию (см. главу 4 для получения дополнительной информации о настройке платформы node.js).

• Вам понадобятся текстовый редактор и веб-браузер. Я рекомендую программу Visual Studio Code (code.visualstudio.com), Atom (atom.io) или Sublime Text (www.sublimetext.com).

• На протяжении всей книги вы будете использовать браузер Chrome, а также встроенные в программу инструменты разработчика. Загрузите дистрибутив браузера на странице www.google.com/chrome.

Об авторе

 

Марк Тиленс Томас (Mark Tielens Thomas) — full-stack-разработчик программного обеспечения и автор. Марк и его супруга живут и работают в Южной Калифорнии. Марк решает проблемы реализации крупных проектов и сотрудничает с ведущими специалистами при разработке высокоэффективных решений. Он религиозен, любит качественный кофе, много читает, обожает быстрые API и отлаженные системы. Пишет книги для издательства Manning и публикует статьи в своем блоге на сайте ifelse.io.

Об обложке

На обложке книги изображен капитан-паша Дерья Бей, адмирал турецкого флота. Капитан-паша был высокопоставленным адмиралом, высшим командиром флота Османской империи. Иллюстрация взята из книги, описывающей коллекцию костюмов жителей Османской империи и опубликованной 1 января 1802 года Уильямом Миллером из «старой» части Бонд-стрит в Лондоне. Обложка той книги утеряна, и мы не смогли узнать ее название. В содержании были приведены подписи рисунков на английском и французском языках, а на каждой иллюстрации указаны имена двух художников, которые работали над ней. Они, безусловно, были бы удивлены, узнав, что их творчество украшает обложку книги по компьютерному программированию… 200 лет спустя.

Книга была куплена сотрудником издательства Manning на антикварном блошином рынке в «Гараже» на 26-й Западной улице на Манхэттене. Продавец приехал из Анкары, и редактор заметил книгу, когда тот уже убирал свой стенд в конце рабочего дня. У редактора не было с собой необходимой суммы наличных денег, а кредитная карта и чек были вежливо отклонены. Вечером продавец улетал обратно в Анкару, поэтому ситуация казалась безнадежной. И каково же было решение? Устное соглашение, скрепленное рукопожатием! Продавец предложил, чтобы деньги были пересланы ему через Интернет, и редактор ушел с листочком с банковскими реквизитами и книгой под мышкой. Излишне говорить, что на следующий день деньги были перечислены. Мы были благодарны этому неизвестному продавцу и впечатлены его доверием. Вспомнился давно забытый способ заключения устных сделок.

Мы, сотрудники издательства Manning, с большим интересом и удовольствием объединяем компьютерную литературу с выпущенными более двух столетий назад книгами, украшая обложки иллюстрациями, основанными на богатом разнообразии жизненного уклада людей тех времен.

Часть I. Обзор React

Если вы работали над клиентскими JavaScript-приложениями последние пару лет, то, вероятно, слышали о библиотеке React. Возможно, вы слышали о ней, хотя только начинаете создавать пользовательские интерфейсы. И даже если узнаете о библиотеке React из этой книги, я все равно окажусь вам полезен: существует много чрезвычайно популярных приложений, которые разработаны с ее участием. Если вы читаете новости на Facebook, смотрите видео на Netflix или обучаетесь информатике на сайте Khan Academy, то используете приложения, созданные с помощью React.

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

В этой книге мы рассмотрим библиотеку React и разберемся, почему возник такой успешный и полезный проект с открытым исходным кодом. В части I вы начнете с основ библиотеки React и изучите ее с нуля. Инструментарий, связанный с созданием качественных JavaScript-приложений с пользовательским интерфейсом, может быть невероятно сложным. Но чтобы не увязнуть в инструментах, сосредоточимся на изучении всех характеристик React API. Попробуем обойтись без «магии» и постараемся понять, как работает библиотека React.

Из главы 1 вы узнаете основное о библиотеке. Мы рассмотрим некоторые важные идеи, такие как компоненты, виртуальная объектная модель документа и компромиссы, на которые придется пойти при использовании React. В главе 2 я проведу быстрый тур по API React и мы построим простой компонент блока комментариев, чтобы попробовать силы в разработке с помощью React.

1. Что такое React

Знакомство с React.

Некоторые концепции и парадигмы React.

Виртуальная объектная модель документа.

Компоненты в React.

React в командной работе.

Компромиссы использования React.

Если вы работаете веб-разработчиком, то, скорее всего, слышали о React. Возможно, читали публикации в Интернете, например в Twitter или Reddit. Или друг (коллега) упомянул о библиотеке, или вы услышали о ней на конференции. Где бы и как это ни произошло, наверняка то, что вы слышали о React, было одобрительным или немного скептическим. Большинство людей хотят составить собственное мнение о таких технологиях, как React. Эффективные и удачные технологии, как правило, получают положительные отзывы. Зачастую немногие понимают эти технологии до того, как они выходят на более широкую аудиторию. Библиотека React тоже начинала с этого, но теперь пользуется огромной популярностью и широко распространена в мире веб-разработки. И ее известность заслуженна, так как она может многое предложить и позволяет внедрять, обновлять или даже трансформировать ваши идеи пользовательских интерфейсов.

1.1. Знакомство с React

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

Как библиотека React вписывается в более широкий мир веб-разработки? Часто говорят, что она стоит в одном ряду с такими проектами, как Vue, Preact, Angular, Ember, Webpack, Redux, и другими известными JavaScript-библиотеками и фреймворками. React часто является важной частью клиентского приложения, и ее функции похожи на присущие библиотекам и фреймворкам, которые я только что упомянул. Фактически сейчас многие популярные интерфейсные технологии относятся к React в большей степени, чем в прошлом. Было время, когда принципы React были новинкой, но с тех пор часть технологий подпала под влия­ние инновационного подхода, основанного на ее компонентах. Библиотека продолжает поддерживать дух переосмысления установленных лучших практик, главная цель которого — предоставить разработчикам выразительную ментальную модель и эффективную технологию для создания приложений пользовательского интерфейса.

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

Компоненты в React должны быть такими, чтобы их можно было легко понять и интегрировать с другими компонентами. Они должны развиваться в соответствии с предсказуемым жизненным циклом, поддерживать собственное внутреннее состоя­ние и работать со старым добрым JavaScript. В дальнейшем мы изучим эти идеи, а сейчас рассмотрим их вкратце. Обзор основных «ингредиентов», которые входят в React-приложение, представляет рис. 1.1. Кратко рассмотрим их.

Компоненты. Это инкапсулированные блоки функциональности, которые являются основой в React. Они используют данные (свойства и состояние) для рендеринга пользовательских интерфейсов (мы рассмотрим, как компоненты React работают с данными, в главе 2 и далее). Некоторые их типы также предоставляют набор методов жизненного цикла, которые вы можете перехватывать (hook), иначе — перехватчики жизненного цикла. Процесс рендеринга (вывод и обновление пользовательского интерфейса на основе ваших данных) в React предсказуем, и компоненты могут подключиться к нему через API React.

• Библиотеки React. React содержит набор основных библиотек. Основная библио­тека React работает с интерактивными библиотеками react-dom и react-native и ориентирована на спецификацию и определение компонентов. Она позволяет создавать дерево компонентов, которые можно использовать для средств визуа­лизации (рендеринга) браузера или другой платформы. react-dom — одно из таких средств, предназначенное для рендеринга в браузере и на стороне сервера. Библиотеки React Native сфокусированы на нативных платформах и позволяют создавать React-приложения для iOS, Android и других платформ.

 

Рис. 1.1. React позволяет создавать пользовательские интерфейсы из компонентов. Последние поддерживают свое собственное состояние, написаны и работают с «ванильным» JavaScript-кодом и наследуют ряд полезных API от React. Большинство React-приложений разработаны для браузеров, но могут использоваться и в таких средах, как iOS и Android. Для получения дополнительной информации о React Native см. книгу React Native in Action, выпущенную издательством Manning

• Сторонние библиотеки. React не поставляется с инструментами моделирования данных, HTTP-вызовов, библиотеками стилей или другими распространенными элементами интерфейсного приложения. Поэтому задействуйте в своем приложении дополнительный код, модули или другие инструменты. И хотя этими общими технологиями React не комплектуется, широкая экосистема, окружающая ее, состоит из невероятно полезных библиотек. Далее будем использовать некоторые из них и даже отведем главы 10 и 11 на то, чтобы изучить Redux — библиотеку для управления состоянием.

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

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

1.1.1. Для кого эта книга

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

Вы легко научитесь создавать React-приложения, если знакомы с основами языка JavaScript и имеете некоторый опыт разработки веб-приложений. Я не буду освещать основы JavaScript. Такие темы, как прототипная модель наследования, стандарт ES2015 и выше, приведение типов, синтаксис, ключевые слова, паттерны асинхронного программирования, такие как async/await, и другие фундаментальные концепции выходят за рамки этой книги. Я просто рассмотрю все, что особенно важно для разработки React-приложений, но не стану глубоко погружаться в язык программирования JavaScript.

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

Возможно, вы уже хорошо знаете язык JavaScript и даже имели дело с React. Это не удивляет, учитывая популярность библиотеки. Если это так, вы лучше поймете некоторые основные концепции React. Тем не менее я не буду рассматривать ряд узких тем, с которыми вы могли столкнуться, работая с библиотекой. Изучить их вы можете, прочитав другие книги издательства Manning, например React Native in Action.

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

1.1.2. Примечание об инструментарии

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

Вам не нужно быть гуру Webpack, Babel и других инструментов, чтобы читать и понимать эту книгу. При создании демонстрационного приложения я применил несколько важных инструментов, и вы сможете просмотреть их конфигурации. Но я не буду подробно описывать их. Инструменты быстро обновляются и изменяются, поэтому их бесполезно глубоко рассматривать в рамках книги. Я обязательно отмечу, если инструменты актуальны или подходят для работы над проектом, но не буду их описывать.

А еще я думаю, что подобный инструментарий способен отвлечь при изучении новых технологий наподобие React. Если вам нужно обдумать несколько новых концепций и парадигм, зачем еще изучать сложный инструментарий? Именно поэтому сначала мы сосредоточимся на изучении «ванильного» React в главе 2, прежде чем переходить к возможностям JSX или JavaScript, реализация которых требует применения инструментов разработки. Но что стоит знать, так это npm. Это инструмент управления пакетами для JavaScript, и мы будем использовать его для установки зависимостей для нашего проекта и выполнения команд для работы с ним в оболочке командной строки. Вероятно, вы уже знакомы с менеджером пакетов npm, но если нет, это не помешает вам читать книгу. Потребуются лишь базовые навыки работы в оболочке командной строки и с менеджером npm. Справочные сведения, касающиеся менеджера пакетов npm, опубликованы на сайте docs.npmjs.com/getting-started/what-is-npm.

1.1.3. Кто использует React

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

Библиотека React стартовала как небольшой проект, а теперь имеет широкую популярность и поддержку. Не существует совершенных проектов, и React не исключение, но, поскольку проекты с открытым исходным кодом, как правило, развиваются эффективнее прочих, у нее есть много важных компонентов для достижения успеха. Более того, проект React включает в себя множество других технологий с открытым исходным кодом. Это кажется сложным, поскольку экосистема может стать огромной, но так она формирует надежное и разнообразное сообщество. На рис. 1.2 показана карта экосистемы React. Я буду рассказывать о различных библиотеках и проектах на протяжении всей книги, но если вам интересно узнать об этом больше, вы найдете руководство по адресу ifelse.io/react-ecosystem. Я буду поддерживать и обновлять ресурс по мере развития экосистемы.

 

Рис. 1.2. Карта экосистемы React разноплановая настолько, что даже не вписывается в мои представления. Если вы хотите получить дополнительную информацию, я опубликовал на сайте ifelse.io/react-ecosystem руководство, которое поможет определить свой путь в экосистеме React

Основной способ прикоснуться к React — это приложения с открытым исходным кодом, которые вы используете ежедневно. Существует много компаний, работа­ющих с React разными интересными способами. Далее перечислены лишь некоторые, применяющие React для своих продуктов: Facebook, Netflix, New Relic, Uber, Wealthfront, Heroku, PayPal, BBC, Microsoft, NFL, Asana, ESPN, Walmart, Venmo, Codecademy, Atlassian, Asana, Airbnb, Khan Academy, FloQast и др.

Эти компании не следуют слепо тенденциям в сообществе JavaScript. У них есть исключительные технические требования, которые влияют на огромное количество пользователей, и им необходимо выполнять разработку в жесткие сроки. Кто-то скажет: «Я слышал, что React — хорошая тема, поэтому мы должны все-таки “реактифицироваться”!» — и не будет прислушиваться к советам менеджеров и других разработчиков. Компаниям и разработчикам нужны хорошие инструменты, которые помогают удачно реализовывать идеи и делать это быстро, создавая высокопроизводительные, масштабируемые и надежные приложения.

1.2. Чего React не делает

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

Но я бы оказал вам плохую услугу, если бы умолчал о некоторых недостатках React и не описал, на что библиотека не способна. Понимание того, что что-то нереализуемо, так же важно, как осознание того, чего можно достичь. Почему? Лучшие технические решения обычно результат компромиссов, а не безапелляционного заявления: «React кардинально лучше, чем инструмент X, потому что нравится мне больше». По поводу последнего выражения: вы, вероятно, имеете дело не с двумя совершенно разными технологиями (COBOL против JavaScript). Надеюсь, вы даже не рассматриваете технологии, которые принципиально не подходят для решения этой задачи. И еще: создание больших проектов и решение технических задач никогда не должны зависеть от чьего-то мнения. Дело не в том, что мнения людей не имеют значения (конечно, это не так), просто они не должны влиять на работу.

Компромиссы. Итак, компромиссы необходимы при оценке и обсуждении программного обеспечения. На какие же компромиссы можно пойти относительно React? Во-первых, библиотеку иногда называют простым представлением. Это может быть неверно истолковано, если вы подумаете, что React — просто система паттернов типа Handlebars или Pug (ne'e Jade) или что эта библиотека — часть архитектуры MCV (модель — контроллер — представление). Все эти утверждения неверны. Библиотека React не только сочетает оба определения, она — нечто намного большее. Для упрощения опишу React как ответ на вопрос «Что это такое?», а не «Чем она не является?» (например, просто представлением). React — это декларативная, основанная на компонентах библиотека для создания пользовательских интерфейсов, поддерживаемых на различных платформах (Всемирная паутина, нативные устройства, мобильные устройства, серверная платформа, настольные устройства и даже устройства виртуальной реальности в будущем (React VR)).

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

HTTP-вызовы;

• создание и проверку веб-форм;

• маршрутизацию;

• форматирование строк и чисел;

• интернационализацию;

• внедрение зависимостей;

• базовые элементы для моделирования данных;

• настраиваемый фреймворк тестирования (хотя это и не так важно, как другие возможности);

• служебные скрипты (SW) включены по умолчанию (подход с поддержкой обслуживания к выполнению JavaScript-сценариев).

Это очень много, и, судя по моему опыту, пользователи, как правило, реагируют на все эти функции во фреймворке двумя способами. Либо «Ничего себе! Мне не нужны все эти функции!», либо «Ничего себе! Я не могу выбрать, как мне что-то сделать!». Суть таких фреймворков, как Angular, Ember и т.п., состоит в том, что обычно существует четко определенный способ сделать что-то. Например, маршрутизация в Angular реализуется с помощью встроенного роутера Angular Router, все задачи по протоколу HTTP выполняются с помощью встроенных HTTP-процедур и т.д.

Нет ничего принципиально неправильного в этом подходе. Я трудился в таких командах, где использовали подобные технологии, и в таких, где пошли более гибким путем и выбирали технологии, которые хорошо помогают сделать что-то конкретное. Мы отлично поработали с обоими подходами, они хорошо зарекомендовали себя. Я предпочитаю принцип «одно, но качественно», но тут важен компромисс. В библиотеке React нет непосредственных решений для HTTP, маршрутизации, моделирования данных (хотя наверняка есть понятие о потоке данных в ваших представлениях, к которым мы стремимся) или другого функционала, схожего с име­ющимся у платформ наподобие Angular. Если ваша команда считает, что в ходе работы над проектом одним фреймворком не обойтись, возможно, React не лучший выбор. Но, по моему опыту, большинство команд одобряют гибкость React, сочетающуюся с ментальной моделью и интуитивно понятными API.

Гибкость React, в частности, заключается в том, что вы можете выбрать наилучшие инструменты для работы. Не нравится, как работает HTTP-библиотека X? Нет проблем, замените ее чем-то другим. Предпочитаете работать с веб-формами иначе? В чем дело, реализуйте свой способ. React предоставляет набор мощных элементов для работы. Справедливости ради стоит сказать: другие фреймворки, типа Angular, как правило, также позволяют заменить что-то, но реально поддерживаемый сообществом способ выполнить поставленную задачу обычно будет встроенным и задействованным.

Очевидный недостаток большей свободы заключается в том, что, если вы привыкли к фреймворкам с более широкими возможностями, например Angular или Ember, вам придется подбирать собственные решения для разных функциональных возможностей своего приложения. Это или хорошо, или плохо в зависимости от таких факторов, как уровень подготовки разработчиков в команде, предпочтения в области управления проектами и другие факторы, характерные для вашей ситуации. Существует много аргументов в пользу как универсального подхода, так и подхода в духе «одно, но качественно». Я склонен придерживаться принципа, который позволяет в каждом конкретном случае принимать гибкие решения таким образом, чтобы команда могла подобрать или создать нужные инструменты. Можно также изучить невероятно большую экосистему JavaScript — вам будет трудно найти что-то относящееся к задаче, которую вы решаете. Но факт остается фактом: отличные высокоэффективные команды используют оба подхода (иногда одновременно!), чтобы достичь результата.

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

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

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

Последний компромисс, который мы должны обсудить, — это реализация и строение React. Ядро React — это системы, автоматически обрабатывающие пользовательский интерфейс, когда изменяются данные в его компонентах. Они вносят изменения, которые могут перехватить, используя так называемые методы жизненного цикла. Мы подробно рассмотрим их в последующих главах. Системы React, поддерживающие обновление пользовательского интерфейса, значительно упрощают создание надежных модульных компонентов, применяемых приложением. То, как библиотека React выполняет бо'льшую часть работы по поддержке пользовательского интерфейса с обновлением данных, — еще одна причина того, что разработчикам нравится работать с React и этот мощный инструмент — в ваших руках. Тем не менее не следует полагать, что у «движков» данной технологии нет недостатков или они не используют компромиссы.

React — это абстракция, что чревато затратами. Создаваемая вами система непрозрачна, потому что построена особым образом и управляется через API. Это означает также, что вам нужно разрабатывать пользовательские интерфейсы в режиме, присущем React. К счастью, API React создают «обусловленные выходы», которые позволяют вам спуститься на более низкие уровни абстракции. Вы все равно можете использовать другие инструменты, такие как jQuery, но делать это стоит с оглядкой на React. Это опять-таки компромисс: упрощенная ментальная модель в обмен на то, что у вас не получится делать абсолютно все, что хочется.

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

1.3. Виртуальная объектная модель документа в React

Мы вкратце поговорили о некоторых возможностях библиотеки React. Я полагаю, что эта информация поможет вам и вашей команде создавать лучшие пользовательские интерфейсы. Частично она связана с ментальной моделью и API, которые предоставляет React. Что скрывается за этим? Основная концепция React — это стремление упростить задачи и исключить ненужную сложность при разработке. Библиотека React пытается сделать все возможное, чтобы быть исполнителем, освобождая вас для того, чтобы вы могли задуматься о других функциях приложения. Этот подход заключается в том, чтобы позволить вам быть декларативным, а не императивным разработчиком. Вы объявляете, как компоненты должны вести себя и выглядеть в разных состояниях, а внутренний механизм React справляется со сложностями управления обновлениями, апгрейдом пользовательского интерфейса для отражения изменений и т.д.

Одним из основных управляющих элементов технологии является виртуальная объектная модель документа (виртуальная DOM, или vDOM). Она представляет собой структуру данных или набор структур данных, имитирующих или отражающих объектную модель документа, которая используется в браузерах. Я говорю «виртуальная объектная модель документа», потому что другие фреймворки, такие как Ember, имеют собственную реализацию подобной технологии. В целом, виртуальная DOM служит промежуточным слоем между кодом приложения и фактической DOM браузера. Как правило, виртуальная DOM позволяет скрыть сложность обнаружения изменений и управления от разработки и перейти к специализированному уровню абстракции. В следующих подразделах мы посмотрим, как этот подход реализуется в React. На рис. 1.3 показана упрощенная схема фактической DOM и ее отношений с виртуальной DOM, которые мы рассмотрим в ближайшее время.

 

Рис. 1.3. Фактическая и виртуальная DOM. Виртуальная DOM в React обрабатывает изменения в данных, а также преобразование событий браузера в события, которые компоненты могут воспринять и на которые могут среагировать. Виртуальная DOM в React нацелена также на оптимизацию изменений, внесенных в DOM ради производительности

1.3.1. Объектная модель документа

Лучший способ убедиться в том, что вы понимаете, как реализована виртуальная DOM в React, — начать с анализа понимания обычной DOM. Если вы хорошо разбираетесь в DOM, перейдите к следующему подразделу. Если же это не так, начнем с важного вопроса: что такое DOM? DOM, или Document Object Model (объектная модель документа), — это программный интерфейс, который позволяет JavaScript-программам взаимодействовать с различными типами документов (HTML, XML и SVG). Для него существуют стандартизированные спецификации, то есть публичная рабочая группа создала стандартный набор функций, которые должны присутствовать в DOM, и варианты поведения модели. Хотя существуют и другие реализации объектной модели документа, DOM в основном ассоциируется с веб-браузерами, такими как Chrome, Firefox и Edge.

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

Возможно, вы использовали DOM API и раньше, просто могли не знать, что это именно он. Всякий раз, когда вы работаете с методом JavaScript, который обращается к данным, модифицирует или сохраняет данные, связанные с чем-то в HTML-документе, вы почти наверняка применяете DOM или связанные с ней API (для получения дополнительных сведений об интерфейсах веб-API см. сайт developer.mozilla.org/ru/docs/Web/API). Это означает, что не все методы, которые вы задействовали в JavaScript, обязательно являются частью этого языка (document.findElemenyById, querySelectorAll, alert и т.д.). Они входят в большую группу интерфейсов веб-API — DOM и других API, которые относятся к браузеру и позволяют взаимодействовать с документами. На рис. 1.4 показана упрощенная версия структуры дерева DOM, которую вы, вероятно, видели на своих веб-страницах.

Общие методы или свойства, которые вы, возможно, задействовали для обновления или запроса веб-страницы, могут включать getElementById, parent.appendChild, querySelectorAll, innerHTML и др. Все они обеспечиваются хостовой средой (в данном случае браузером) и позволяют JavaScript взаимодействовать с DOM. Без этого у нас было бы гораздо меньше интересных способов использования веб-приложений и исчезла бы необходимость в книгах о React!

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

 

Рис. 1.4. Простая версия структуры дерева DOM, в которой используются элементы, вероятно, вам знакомые. Интерфейс DOM API, который применяется JavaScript, позволяет выполнять операции над этими элементами в дереве

1.3.2. Виртуальная объектная модель документа

Итак, веб-API в браузерах позволяет нам взаимодействовать с веб-документами с помощью JavaScript через DOM. Но если мы уже достигли этого, зачем делать что-то еще? Для начала я хочу отметить, что реализация виртуальной DOM в React не означает, что обычные веб-API плохи или уступают ей. Без них React не может функционировать. Тем не менее в крупных веб-приложениях с DOM возникают кое-какие неприятности. Как правило, они проявляются в области обнаружения изменений. Когда данные изменяются, нужно обновить пользовательский интерфейс, чтобы отразить изменения. Эффективно и просто реализовать это бывает трудно, и React призвана решить эту проблему.

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

При создании приложения значительного размера, имеющего дело с данными, которые меняются с течением времени, и управлении им часто требуется внести много изменений в DOM. Они нередко конфликтуют или выполняются неоптимальным способом. Это способно чрезмерно усложнить систему, так что разработчикам станет непросто с ней работать, а пользователи могут в ней заблудиться. Таким образом, производительность — еще одно ключевое соображение при построении и реализации React. Использование виртуальной DOM помогает решить эту проблему, и следует отметить, что она разработана довольно быстрой. Надежный API, простая ментальная модель и другие особенности, такие как кросс-браузерная совместимость, в итоге становятся более важными результатами виртуальной DOM в React, чем результат от чрезмерного внимания к производительности. Я об этом говорю, так как вы можете услышать, что виртуальная DOM — это что-то вроде «серебряной пули» для производительности. Да, она производительна, но отнюдь не волшебно, к тому же многие другие преимущества этой модели более важны для работы с React.

1.3.3. Обновления и отличия

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

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

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

 

Рис. 1.5. Процедура обновления и учета изменений в React. Когда происходит изменение, React определяет различия между фактическими и внутренними объектами DOM. Затем библиотека эффективно обновляет DOM браузера. Этот процесс часто называют сверкой («что изменилось?») или патчем («обновлять только то, что изменилось»)

1.3.4. Виртуальная DOM: жажда скорости

Как я уже отмечал, виртуальная DOM характеризуется чем-то большим, чем просто скоростью. Она производительна за счет структуры и, как правило, позволяет создавать энергичные и быстрые приложения, которые соответствуют потребностям современных веб-пользователей. Производительность и отличная ментальная модель настолько понравились разработчикам, что многие популярные библио­теки JavaScript создают собственные версии или вариации виртуальной DOM. Даже в этих случаях люди склонны думать, что виртуальная DOM ориентирована в первую очередь на производительность. Производительность — ключевая особенность React, но это второе преимущество после простоты. Виртуальная DOM позволяет не задумываться о сложной логике состояния и сосредоточиться на других, более важных функциях приложения. Скорость и простота улучшают настроение пользователей и разработчиков — это бесспорно!

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

1.4. Компоненты — базовая единица React

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

1.4.1. Компоненты в целом

Что такое компонент? Если простыми словами, то это часть большего целого. Идея компонентов, скорее всего, вам знакома, и вы, вероятно, часто их видите, даже если этого не понимаете. В качестве как ментального, так и визуального инструмента они позволяют добиться при проектировании и разработке пользовательских интерфейсов улучшенного, интуитивно более понятного структурирования и использования приложений. Компонент может быть тем, чем вы его определите, хотя и не все следует относить к ним. Например, если вы решите, что весь интерфейс — это компонент, без дочерних структур или других компонентов, то примете неправильное решение. Вместо этого полезно разбить разные элементы интерфейса на части, которые можно собрать вместе, многократно применить и легко реорганизовать.

Чтобы разобраться в том, что такое компоненты, рассмотрим образец интерфейса и разделим его на составляющие. На рис. 1.6 показан пример интерфейса, над которым мы будем работать в книге. Пользовательские интерфейсы часто содержат элементы, которые используются многократно или перепрофилируются в других частях интерфейса. И даже если они не применяются повторно, то по крайней мере различаются. Эти отдельные элементы интерфейса можно рассматривать как компоненты. На рис. 1.6, слева, показан пример интерфейса, разбитого на компоненты (справа). Мы будем работать над этим интерфейсом позже.

Упражнение 1.1. Разберитесь с компонентами

Посетите популярный сайт, который вам нравится (например, GitHub), и разделите его интерфейс на компоненты. В процессе этого вы, вероятно, обнаружите, что дробите его на все более мелкие части. Когда нужно остановиться? Должно ли отдельное сообщение быть компонентом? Когда имеет смысл использовать мелкие компоненты? Когда целесообразно рассматривать группу элементов как один компонент?

 

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

1.4.2. Компоненты в React: инкапсулированные и многоразовые

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

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

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

Компоненты в React предназначены для совместной работы. Это означает, что вы можете собирать их вместе для создания новых составных компонентов. Формирование структур из компонентов — одна из самых мощных возможностей библиотеки React. Создав компонент один раз, сделайте его доступным для многократного применения в остальной части приложения. Это особенно полезно в крупных приложениях. Если вы работаете в команде среднего или большого размера, публикуйте компоненты в частном реестре (npm и т.п.), где другие команды легко их найдут и используют в новых или существующих проектах. Этот сценарий может не подойти для некоторых команд, но даже более мелкие команды получат выгоду от того, что публикуются компоненты для многократного применения кода.

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

1.5. React для командной работы

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

Итак, что превращает React в отличный инструмент для крупных команд и сложных приложений? Во-первых, простота использования. Простота — это не то же самое, что легкость. Легкие решения часто «грязные», быстрые и, что хуже всего, порождают технический долг. Истинно простая технология гибка и надежна. React реализует это, предоставляя мощные абстракции, с которыми все еще можно работать, обеспечивая погружение в детали нижнего уровня, когда это необходимо. Простую технологию легче понять и применять, потому что была проделана сложная работа по оптимизации и устранению всего лишнего. Библиотека React во многом упростилась, обеспечив эффективное решение без введения вредоносной «черной магии» или непрозрачного API.

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

React — довольно простая библиотека с точки зрения обязанностей и функциональности и этим, безусловно, отличается от аналогов. Если фреймворк типа Angular может потребовать приобретения более сложного API, то React затрагивает только ваше приложение. Это означает, что эту библиотеку гораздо проще интегрировать в текущие проекты, что даст вам время на проработку других характеристик. Некоторые фреймворки и библиотеки придерживаются позиции «все или ничего», а область действия React ограничивается только представлением, и общая совместимость с JavaScript означает, что не всегда все так просто.

Вместо того чтобы придерживаться принципа «все включено», вы можете постепенно переходить к другим проектам или инструментам для React, не меняя радикально структуру, стек или другие связанные области. Это положительная черта любой технологии, и именно так React была впервые опробована в Facebook — в небольшой области проекта. Оттуда она и начала распространяться, так как все больше команд видели и оценивали ее преимущества. Что все это значит для вашей команды? Это значит, что реально задействовать React, не переписывая полностью код проекта.

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

1.6. Резюме

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

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

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

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

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

React — это библиотека для создания пользовательских интерфейсов, созданная разработчиками из компании Facebook.

• React предоставляет простой, гибкий API, основанный на компонентах.

• Компоненты являются фундаментальной единицей React и широко используются в React-приложениях.

• React реализует виртуальную DOM — прослойку между вашей программой и фактической DOM браузера.

• Виртуальная DOM позволяет эффективно обновлять фактическую DOM с использованием алгоритма быстрой сверки.

Виртуальная DOM обеспечивает отличную производительность, но самое большое преимущество — это статическая ментальная модель, которую она обеспечивает.

Теперь, когда мы знаем немного больше об истории и строении библиотеки React, можем приступить к работе с ней. В следующей главе создадим свой первый компонент и рассмотрим, как работает React. Вы больше узнаете о виртуальных DOM, компонентах и о том, как создавать собственные компоненты.

2. <Hello world! />: наш первый компонент

Размышления о пользовательских интерфейсах с компонентами.

Компоненты в React.

Как React рендерит компоненты.

Различные способы создания компонентов в React.

Использование JSX в React.

В главе 1 были даны теоретические основы React. Если вы жаждете увидеть примеры кода, эта глава для вас. В ней мы подберемся к React поближе. Рассматривая API React, вы создадите простой блок комментариев, который поможет увидеть механику React в действии и освоить ментальную модель работы библиотеки. Мы начнем с создания компонентов React без какого-либо синтаксического сахара или удобств, которые могут скрыть базовую технологию. Поэтому в конце главы рассмотрим JSX (упрощенный язык разметки, который поможет быстрее создавать компоненты React). В следующих главах мы перейдем к более сложным моментам и увидим, как создать из компонентов React полноценное приложение (оно будет называться Letters Social — посмотрите на сайте social.react.sh), а в этой главе ограничимся лишь несколькими связанными компонентами.

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

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

• Библиотеки React — React-приложения работают, используя библиотеки React. Основную библиотеку React (react) поддерживают библиотеки react-dom и react-native. В React DOM обрабатывает рендеринг в браузере или в серверных средах, тогда как React Native предоставляет собственные привязки, которые позволяют вам создавать React-приложения для iOS или Android.

 

Рис. 2.1. Это очень краткая схема React, которую вы уже видели в главе 1. С помощью React вы можете использовать компоненты для создания пользовательских интерфейсов, которые могут выполняться в браузерах и на нативных платформах, таких как iOS и Android. Это не всеобъемлющий фреймворк — у вас остается свобода выбора библиотек, которые применяются для моделирования данных, стилизации, HTTP-вызовов и т.д. Вы можете запускать React-приложения в браузерах и с помощью React Native на мобильных устройствах

• Сторонние библиотеки — React не навязывает собственные подходы к моделированию данных, HTTP-вызовам, конкретным областям стилизации, таким как внешний вид, и другим составляющим вашего приложения. Вы будете интегрировать другие технологии для создания своего приложения по собственному усмотрению. Не все библиотеки совместимы с React, но есть способы интегрировать в нее основную их массу. Мы рассмотрим использование кода, отличного от React, в React-приложениях в главах 4, 10 и 11.

• Запуск React-приложения — React-приложение, созданное из компонентов, работает на выбранной вами платформе: веб-сайте, мобильной или нативной.

2.1. Введение в компоненты React

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

 

Рис. 2.2. Обзор компонента React. В дальнейшем мы рассмотрим каждую из этих ключевых частей

Предположим, что мы являемся сотрудниками вымышленного стартапа под названием Letters. Вы создадите социальную сеть следующего поколения, где можно будет размещать информацию, комментировать и ставить «лайки». В этой главе мы исследуем React как потенциальный выбор технологии для вашей компании. Вам было поручено создать простой набор компонентов, чтобы получить представление о технологии. У вас есть лишь грубый набросок, полученный от команды дизайнеров. На рис. 2.3 показана красивая версия того, что вы создадите.

 

Рис. 2.3. Грубый макет блока комментариев. Вы создадите пользовательский интерфейс, в котором пользователи могут добавлять комментарии к сообщению и просматривать предыдущие комментарии

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

Упражнение 2.1. Пересмотрите разбивку интерфейса

Прежде чем читать дальше, найдите время, чтобы вернуться к упражнению 1.1 из предыдущей главы. Вы изучили веб-интерфейс и потратили некоторое время, чтобы разметить его самостоятельно. Затратьте еще минутку, чтобы пересмотреть тот же интерфейс и подумать, не разделите ли вы его на компоненты по-другому теперь, когда больше знаете об этих структурах React. Сгруппируете ли что-то иначе? Далее показан размеченный интерфейс страницы профиля на сайте GitHub из главы 1, чтобы освежить вашу память:

 

2.1.1. Данные приложения

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

Веб-API

Возможно, в процессе работы или обучения вы слышали термин API. Если вы уже знакомы с данной концепцией, пропустите эту врезку. Если нет, она поможет вам разобраться. Что такое API? API (application programming interface — интерфейс программирования приложений)это набор подпрограмм и протоколов для создания программного обеспечения. Определение может показаться размытым и слишком общим. API — это широкий термин, применимый к множеству явлений — от платформ компании до библиотек с открытым исходным кодом.

В веб-разработке и дизайне API практически стал синонимом удаленного публичного API на основе Всемирной паутины. Это означает, что API обычно представляет собой способ взаимодействия с программой или платформой, чаще всего через Интернет. Существует много примеров, два наиболее распространенных — это API Facebook и Stripe. Они предоставляют набор методов для взаимодействия со своими программами и данными через Интернет.

Команда серверных разработчиков из Letters — нашей вымышленной компании — создала для вас такой API. Существует много разных форм и типов веб-интерфейсов API, в этой книге вы будете работать с RESTful JSON API. Название означает, что сервер предоставляет данные в формате JSON и доступные данные организованы вокруг таких ресурсов, как пользователи, сообщения, комментарии и т.д. RESTful JSON — распространенные удаленные API, поэтому, вероятно, это не последний раз, когда вы с ним работаете.

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

Листинг 2.1. Примерный JSON API

 

 

API возвращает ответ в формате JSON, содержащий отдельную публикацию. У него есть важные свойства, включая id, content, author и comments. id — число, content и author — строки, а comments — это массив объектов. У каждого комментария есть собственные идентификатор, пользователь, который сделал комментарий, и содержимое комментария.

2.1.2. Несколько компонентов: гибридные и родственные отношения

У вас есть необходимые данные и макет, но как вы собираетесь создавать компоненты для использования этих данных? Во-первых, нужно знать, как их организуют для взаимодействия с другими компонентами. Компоненты React соединены в древовидные структуры. Как и DOM-элементы, они могут быть вложенными и содержать другие компоненты. А еще появляться рядом с другими компонентами, что означает: они встречаются на одном и том же уровне (рис. 2.4).

Напрашивается важный вопрос: в каких отношениях могут состоять компоненты? Вы, вероятно, думаете, что существует довольно много разных типов отношений, создаваемых с применением компонентов, и в некотором смысле вы правы. Способы их использования гибкие. Поскольку они самодостаточны и, как правило, не несут никакого «багажа», их называют составными.

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

Поскольку компоненты являются составными, их можно применять в разных позициях кода приложения. Где бы они ни использовались, они помогают сформировать определенный тип отношений — родительский или дочерний. Если один компонент содержит другой, он считается родительским. А тот, который находится внутри другого, — дочерним (потомком). Компоненты, находящиеся на одном уровне, не связаны между собой, хотя могут располагаться рядом друг с другом. Они только «заботятся» о своих родителях и детях.

 

Рис. 2.4. Компоненты могут иметь разные типы отношений (родительский и дочерний), использоваться для создания других компонентов или же быть автономными. Зачастую их можно легко перемещать, потому что они самодостаточны и не тянут за собой «багаж». Они называются составными

На рис. 2.4 показано, как компоненты могут относиться друг к другу в родственном представлении и соединяться для создания новых компонентов. Обратите внимание на отсутствие непосредственных отношений между двумя сестринскими компонентами, несмотря на прямую связь между родителем и потомком. Я остановлюсь на этом подробнее в ходе исследования потока данных в React.

2.1.3. Установление отношений компонентов

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

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

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

• Если элемент интерфейса повторяется несколько раз, он, как правило, хороший кандидат на то, чтобы стать компонентом.

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

Учитывая данные рекомендации, взгляните на доступные данные и макет и на­чните с разбивки интерфейса на несколько компонентов. На рис. 2.5 показан один из способов сделать это.

 

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

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

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

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

2.2. Создание компонентов в React

В этом разделе вы создадите несколько компонентов React и запустите их в браузере. Вам не понадобится платформа node.js или что-то подобное, чтобы настроить и запустить их. Вы запустите код в браузере через посредника — сайт CodeSandbox (codesandbox.io). Если предпочитаете редактировать файлы на локальном компьютере, можете нажать кнопку Download (Скачать) в окне редактора кода на сайте CodeSandbox и скачать код для этого примера.

Для своих первых компонентов вы будете использовать три библиотеки: React, React DOM и prop-types. React DOM — это средство рендеринга для React, которое было отделено от основной библиотеки React, чтобы лучше разделить задачи. Оно обрабатывает компоненты рендеринга DOM или строку для рендеринга на стороне сервера. prop-types — это библиотека разработки, которая поможет выполнить проверку типов данных, переданных вашим компонентам.

Вы разработаете компонент блока комментария, вначале создав его составные части. Так вы лучше поймете, что происходит, когда React создает и отображает ваши компоненты. Вам нужно добавить новый DOM-элемент с идентификатором root, а также некоторый базовый код, необходимый React DOM. В листинге 2.2 показано размещение компонента. Для каждого листинга я приведу ссылку на версию кода в Интернете, где можно его редактировать и экспериментировать с ним.

Листинг 2.2. Погнали!

 

Код листинга 2.2 доступен в Интернете по адресу codesandbox.io/s/vj9xkqzkvy.

2.2.1. Создание элементов React

Пока ваш код умеет только загружать библиотеки React и искать DOM-элемент root. Чтобы сделать что-то существенное, нужно использовать React DOM. Для создания компонента и управления им необходимо вызвать метод render для React. Вы вызовете этот метод с компонентом для рендеринга и элементом container (DOM-элемент, который вы ранее сохранили в переменной). Синтаксис ReactDOM.render выглядит так:

ReactDOM.render(

  ReactElement element,

  DOMElement container,

  [function callback]

) -> ReactComponent

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

Определение

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

Элементы — это дескрипторы, которые мы используем, чтобы сообщить React, что хотим видеть на экране, они являются центральной концепцией React. Большинство ваших компонентов будут коллекциями элементов React, они создадут «граничное» окружение вокруг части вашего пользовательского интерфейса, чтобы можно было группировать функциональность, разметку и стили. Но что означает фраза «Элемент React является виртуальным представлением DOM-элемента»? То, что элементы React должны относиться к React, как DOM-элементы относятся к DOM — базовым примитивам, из которых состоит пользовательский интерфейс. Когда вы верстаете обычную HTML-разметку, то задействуете различные типы элементов (div, span, section, p, img и т.д.) для хранения и структурирования информации. В случае с React можно использовать элементы React, которые сообщают библиотеке о компонентах React или обычных DOM-элементах, которые вы хотите рендерить, для компоновки и создания пользовательского интерфейса.

Возможно, параллель между DOM-элементами и элементами React не сразу станет вам понятна. Это нормально. Помните, как React должна помочь вам, предоставив лучшую ментальную модель для работы? Параллель между DOM-элементами и элементами React — один из способов достижения цели. Это означает, что вы получаете знакомую ментальную структуру — древовидную структуру элементов, похожую на обычные DOM-элементы. Выявить некоторое сходство между элементами React и DOM-элементами поможет рис. 2.6.

 

Рис. 2.6. Виртуальная и фактическая DOM имеют сходную древовидную структуру, благодаря чему становится проще понять структуру компонентов и общие принципы React-приложения. DOM состоит из элементов DOMElement (HTMLElement и SVGElement), тогда как виртуальная DOM React — из элементов ReactElement

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

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

React.createElement(

  String/ReactClass type,

  [object props],

  [children...]

) -> React Element

 

Рис. 2.7. Библиотека React с помощью элементов React создает виртуальную DOM, которой React DOM будет управлять и которую будет использовать для согласования и обновления фактической DOM. Это простые схемы, применяемые React при создании элементов и управлении ими

Функция React.createElement принимает строку или компонент (либо класс, расширяющий React.Component, либо функцию), объект свойств и дочерние элементы и возвращает элемент React. Помните: элемент React представляет собой простое представление желаемого результата рендеринга средствами React. Он указывает либо на DOM-элемент, либо на другой компонент React.

Подробнее рассмотрим основные инструкции.

type — вы можете передать либо строку, которая является именем тега создаваемого HTML-элемента ("div", "span", "a" и т.д.), либо класс React, который мы рассмотрим в ближайшее время. Подумайте об этом в контексте «Что я собираюсь создавать?».

• props — краткое название свойств. Объект props позволяет указать, какие атрибуты будут определены в HTML-элементе (если в контексте ReactDOMElement) или будут доступны экземпляру класса компонента.

• children... — помните, я говорил, что компоненты React являются составными? Здесь вы можете составить их несколько. Используя строку children... и аргумен­ты, переданные после type и props, можно разместить, упорядочить и даже вложить дополнительные элементы React. Как вы увидите в листинге 2.3, реально встраивать элементы React, вставляя вызовы в React.createElement в children....

Функция React.createElement задает вопросы «Что я создаю?», «Как это настроить?» и «Что в нем содержится?». Далее показано, как применять функцию React.createElement.

Код из листинга 2.3 доступен по адресу codesandbox.io/s/qxx7z86q4w.

Листинг 2.3. Использование функции React.createElement

 

2.2.2. Рендеринг вашего первого компонента

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

 

Рис. 2.8. Ваш первый компонент. Результат не особенно впечатляет, но это настоящий компонент React!

Отлично, однако вам может быть интересно, как React превращает функции React.createElement в то, что вы видите на экране. Библиотека задействует элементы React, предоставляемые вами для создания виртуальной DOM, которую может использовать React DOM, управляя DOM браузера. Помните из рис. 2.4, что виртуальные и фактические DOM имеют сходные структуры? Так и React должна создать собственную виртуальную структуру дерева DOM из ваших элементов React, прежде чем выполнит свою работу.

Для этого React рекурсивно оценивает все свойства children... каждого вызова функции React.createElement, передавая результат родительскому элементу. Может показаться, что React ведет себя как ребенок, который спрашивает: «Что такое X?» — пока не разузнает все об X. На рис. 2.9 представлено, как библиотека обрабатывает вложенные элементы React. Идите по стрелкам вниз и вправо, чтобы увидеть, как React исследует children... каждого элемента React, пока не сформирует полное дерево.

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

 

Рис. 2.9. React рекурсивно оценивает ряд элементов React, чтобы определить, как нужно сформировать виртуальную структуру дерева DOM для ваших компонентов. Она также проверит наличие дополнительных элементов React в children… React пройдет всеми возможными путями, как ребенок, спрашивающий: «Что такое X?» — пока не узнает все, что хочет, и не успокоится. Идите по стрелкам вниз и вправо, чтобы понять, как React обрабатывает вложенные элементы React, а также запрашивает каждый параметр

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

Упражнение 2.2. Элементы React

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

Элементы React получают строку, чтобы создать DOM-элемент определенного типа (div, a, p и т.д.).

Вы можете предоставить конфигурацию элементу React через объект props; он аналогичен атрибутам, которые могут иметь DOM-элементы (к примеру, <img src = "Url-адрес" />).

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

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

Из элементов React состоят компоненты React.

2.2.3. Создание компонентов React

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

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

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

2.2.4. Создание классов React

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

class MyReactClassComponent extends Component {

    render() {}

}

Вместо того чтобы ссылаться на конкретный метод из библиотеки React, как вы делали с функцией React.createElement, для создания компонента с помощью функции React.Component объявляется класс JavaScript, который наследуется от абстрактного базового класса React.Component. Этому классу обычно необходимо определить метод рендеринга, который будет возвращать один элемент или массив элементов React. Старый способ создания классов React работал с помощью метода createClass. С появлением классов в JavaScript все изменилось, и тот способ теперь не используется, хотя вы все еще можете задействовать модуль create-react-class, доступный в менеджере npm. Подробные сведения о применении библиотеки React без ES2015 + JavaScript найдете на сайте reactjs.org/docs/react-without-es6.html.

2.2.5. Метод рендеринга

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

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

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

 

Рис. 2.10. React создаст в памяти экземпляр поддержки для компонентов, созданных как классы компонентов React. Классы компонентов React получают такой экземпляр, а элементы React и компоненты класса, не относящегося к React, — нет. Помните, что элементы React являются зеркалами DOM, а компоненты — способом их группировки. Экземпляр поддержки — это способ хранения данных конкретного компонента и доступа к ним. Данные, хранящиеся в экземпляре, будут доступны для метода рендеринга компонента с помощью определенных методов API. Это означает, что вы получаете доступ к данным, которые можете изменить и которые будут сохраняться с течением времени

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

В листинге 2.5 в следующем подразделе вы увидите компонент класса React в действии. Будет создано множество вложенных элементов React, и с помощью метода this.props будут переданы пользовательские данные. То, что свойство используется с классами React, похоже на создание пользовательского HTML-элемента, такого как Jedi, и предоставления ему настраиваемого атрибута, например name: <Jedi name = "Obi Wan"/>. Я расскажу о ключевом слове this в последующих главах, и обратите внимание на то, что в этом случае зарезервированное ключевое слово this языка JavaScript указывает на экземпляр компонента.

2.2.6. Проверка свойств с помощью PropTypes

Вы знаете, что компоненты класса React могут задействовать пользовательские свойства, и это замечательно: вы будто можете создавать собственные HTML-элементы, но с расширенной функциональностью. Помните, что с большей мощью приходит бо'льшая ответственность. Вам нужен какой-то способ проверять, какие свойства вы будете использовать, чтобы иметь возможность предотвратить ошибки и планировать виды данных, которые станут применять компоненты. Для этого годятся средства проверки (валидаторы), доступные в React в пространстве имен PropTypes. Набор валидаторов PropTypes входил в основную библиотеку React, но позже был испорчен и помечен как устаревший в версии React 15.5. Чтобы использовать PropTypes, необходимо установить пакет prop-types, который по-прежнему является частью инструментария React, но уже не включен в основную библиотеку. Этот пакет имеется в исходном коде приложения и примерах на сайте CodeSandbox, с которыми вы работаете в данной главе.

Библиотека prop-types предоставляет набор валидаторов, позволяющих указать свойства, в которых нуждается или которых ожидает ваш компонент. Например, вы собираетесь создать компонент ProfilePicture, но это не будет иметь большого смысла без изображения (или логики для обработки, если нет ни одного изображения). Используйте PropTypes, чтобы указать, какие свойства должны быть обработаны компонентом ProfilePicture и как они выглядят.

Применение PropTypes — это предоставление своего рода контракта, который может быть выполнен или нарушен другими разработчиками или вами в будущем. Для работы React PropTypes необязателен, но рекомендован: он позволяет предотвратить ошибки и упростить отладку. Еще одно преимущество работы с PropTypes заключается в следующем: если вы укажете, каких свойств ожидаете в первую очередь, то сможете задуматься о том, что вашему компоненту нужно для работы.

Задействуя PropTypes, необходимо добавить свойство propTypes в класс React.Com­ponent с помощью свойства статического класса или простым присвоением свойств после определения класса. Обратите внимание на нижний регистр имени свойства класса, в отличие от объекта React, так как код легко перепутать. Листинг 2.4 показывает, как используется PropTypes, а также возвращаются элементы React из компонентов класса React. В этом листинге вы создаете класс React, который можете передать функции createElement, добавляете метод render и указываете propTypes.

Листинг 2.4. Применение PropTypes и метода render

 

Код листинга 2.4 доступен по адресу codesandbox.io/s/3yj462omrq.

Вы должны увидеть текст: Mark said: This is a post!. Если вы не обеспечили определенные свойства, то увидите предупреждение в консоли разработчика. Отсутствие нужных свойств может привести к нарушению работы приложения, так как неизвестно, какие компоненты должны работать, а валидация при этом будет пройдена. Другими словами, если вы забудете предоставить приложению важную часть данных, вероятно, оно не будет функционировать правильно, а проверка PropTypes окажется выполнена и вы получите сообщение, что не указаны свойства. Поскольку PropTypes анализирует тип только в режиме разработки, приложение, работающее в обычном режиме, не запустит PropTypes.

Теперь, когда вы создали компонент и передали ему данные, попробуйте реализовать вложенные компоненты. Я уже упоминал об этой возможности — одной из многих, делающих React удобной для работы и мощной: компоненты создаются из других компонентов. Листинг 2.5 иллюстрирует этот процесс и демонстрирует специальное использование свойства children. Я расскажу об этом подробнее в следующих главах, когда вы начнете изучать маршрутизацию и компоненты более высокого порядка. Применение свойства this.props.children сродни выводу вложенных данных. В этом случае вы создаете компонент Comment, передаете его как аргумент и получаете его вложение.

Листинг 2.5. Добавление вложенного компонента

 

 

Код из листинга 2.5 доступен по адресу codesandbox.io/s/k2vn448pn3.

Теперь, когда создан вложенный компонент, вы сможете увидеть больше контента в своем браузере.

Далее рассмотрим, как используется упомянутое ранее встроенное состояние, доступное с классами React, для создания динамических компонентов.

Упражнение 2.3. Обратная разработка дерева компонентов

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

 

 

Как бы вы сформировали аналогичную структуру компонентов, но в React? (Можете присваивать имена всем классам CSS.)

2.3. Время жизни и время компонента

В этом разделе вы добавите к компонентам Post и Comment код, позволяющий сделать их интерактивными. Ранее мы обнаружили, что компоненты, созданные как классы React, используют специальные способы хранения и доступа к данным через экземпляры поддержки. Чтобы понять это, рассмотрим общие принципы работы React. На рис. 2.11 суммируется то, что вы узнали до сих пор. Можете создавать компоненты из классов React, которые образуются из элементов React (элементы, которые отображаются в DOM). Я называю классами React подклассы React.Component, с которыми способна работать функция React.createElement.

Компоненты, образованные из классов React, имеют экземпляры поддержки, которые позволяют хранить данные и должны обладать методом render, возвращающим ровно один React-элемент. Библиотека будет принимать элементы React, создавать из них виртуальную DOM в памяти и поддерживать управление и обновление DOM.

Вы добавили метод render и проверку PropTypes в классы React. Но для создания динамических компонентов вам понадобится еще кое-что. Классы React могут иметь специальные методы, которые будут вызываться в определенном порядке, так как React управляет виртуальной DOM. Метод render, который вы использовали для возврата элементов React, — лишь один из них.

В дополнение к зарезервированным методам жизненного цикла можете добавить собственные методы. React дает вам свободу и гибкость для добавления любых функций, требующихся вашим компонентам. Практически все, что действительно применимо в JavaScript, можно задействовать в React. Если вы взглянете на рис. 1.1, то заметите, что методы жизненного цикла, специальные свойства и пользовательский код составляют бо'льшую часть компонента React. Что же еще осталось?

2.3.1. «Реактивное» состояние

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

Два основных типа состояния — изменяемое и неизменяемое. Подумайте о различии между ними с точки зрения времени. Может ли состояние измениться после создания? Если да, его называют изменяемым, если нет — неизменяемым. Эти темы рассматриваются в различных научных областях, поэтому я не буду в них углуб­ляться.

 

Рис. 2.11. Масштабирование при рендеринге в React. Классы и элементы применяют React для создания в памяти виртуальной DOM, которая управляет фактической DOM. Библиотека создает также «синтетическую» систему событий, чтобы вы могли реагировать на события из браузера, например щелчки кнопкой мыши, прокрутку и другие пользовательские события

В React компоненты, созданные как классы JavaScript (developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Classes), которые расширяют React.Component, могут находиться как в изменяемом, так и в неизменяемом состоянии, тогда как компоненты, созданные из функции (функциональные компоненты без состояния), имеют доступ только к неизменяемому состоянию (свойствам — props). Я расскажу об этом в следующих главах, а пока буду придерживаться компонентов, которые наследуются от React.Component и получают состояние и дополнительные методы. В них состояние доступно из свойства this.state экземпляра класса. Неизменяемое состояние доступно с помощью this.props, который вы уже использовали для создания статических компонентов.

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

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

Состояние и свойства являются механизмами для данных, из которых состоит ваше приложение, и тем, что делает его полезным. Если вы создаете приложение для социальной сети (займемся этим в следующих главах), то часто будете задействовать комбинацию свойств и состояния для создания компонентов, отображающих пользовательскую информацию, обновления и т.д. Если применяете React для рендеринга данных, можете использовать свойства и состояние в качестве ввода для библиотек рендеринга, таких как D3.js. Независимо от того, что разрабатывается, вы, вероятно, будете с помощью состояния и свойств управлять информацией в своем приложении React.

Упражнение 2.4. Изменяемое и неизменяемое

Прежде чем читать дальше, проверьте свои знания о различиях между двумя основными типами данных в React — изменяемыми и неизменяемыми. Обозначьте каждое утверждение как истинное или ложное (И | Л).

Изменяемое состояние означает, что данные могут меняться со временем: И | Л.

Доступ к состоянию в React получают с помощью свойства this.state: И | Л.

props — изменяемый объект, предоставляемый React: И | Л.

Неизменяемые данные со временем не меняются: И | Л.

Доступ к свойствам осуществляется через this.props: И | Л.

2.3.2. Установка начального состояния

Когда нужно использовать состояние и как начать это делать? Простой ответ таков: когда вы хотите внести изменения в данные, хранящиеся в компоненте. Я говорил, что свойства были неизменяемыми (изменить их нельзя), поэтому, если нужно изменить данные, следует изменить состояние. В React данные, которые должны изменяться, зачастую введены пользователем (часто это текст, файлы, выбранные опции и т.д.), но вероятно и множество других вариантов. Чтобы отслеживать взаимодействие пользователей с элементами формы, вам необходимо установить начальное состояние и со временем изменить его. Для установки начального состоя­ния вашего компонента — компонента блока комментариев, который основывается на идеях и концепциях из предыдущих листингов, можете применять конструктор компонента. Это позволит добавлять комментарии к сообщению с помощью простой формы. В листинге 2.6 показано, как настроить компонент и задать начальное состояние.

Листинг 2.6. Установка начального состояния

 

 

Код листинга 2.6 доступен по адресу codesandbox.io/s/p5r3kwqx5q.

Чтобы обновить состояние, которое вы инициализировали в конструкторе класса компонента, следует использовать специальный метод: вы не можете просто перезаписать this.state, как могли бы сделать в случае работы не с React. Так происходит потому, что React должна отслеживать состояние и обеспечивать постоянную синхронизацию виртуальной и фактической DOM. Чтобы обновить состояние в классе компонента React, применяйте метод this.setState; синтаксис которого приведен далее. Для обновления состояния требуется функция обновления, которая ничего не возвращает:

setState(

  function(prevState, props) -> nextState,

  callback

)-> void

Метод this.setState принимает функцию обновления, возвращающую объект, который будет частично превращаться в состояние. Например, если вы изначально задали свойство имени пользователя (username) как пустую строку, нужно применить метод this.setState, чтобы установить новое имя пользователя в качестве состояния вашего компонента. React примет это значение и обновит скрытый экземпляр и DOM с новым значением.

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

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

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

Листинг 2.7. Настройка обработчиков событий

 

 

Код из листинга 2.7 доступен по адресу codesandbox.io/s/x9mxo31pxp.

Вы обратили внимание, как используется метод .bind в конструкторе класса компонента? В предыдущих версиях React библиотека автоматически привязывала методы к экземпляру вашего компонента. Однако с переходом на классы JavaScript делать это придется самостоятельно. Если вы определили компонентный метод и он не работает, убедитесь, что правильно связали свои методы, — это легко забыть при первом знакомстве с React.

Затем попробуйте не применять обработчики событий onChange и посмотрите, получится ли ввести что-либо в поля формы. Ничего не получится, так как React отслеживает синхронизацию фактической DOM с виртуальной, которая не обновляется, и, таким образом, не позволит изменить DOM. Если вы сейчас не понимаете тему до конца, не волнуйтесь — в главах 5 и 6 формы рассматриваются более подробно.

Теперь, когда получен способ прослушивания событий и изменения состояния компонента, можете реализовать способ создания новых комментариев с использованием однонаправленного потока данных. В React потоки данных передаются сверху вниз, от родителей к потомкам (дочерним компонентам). При создании составных компонентов можно передавать информацию дочерним компонентам через свойства и применять их в дочерних компонентах. Это означает, что вы можете хранить данные из компонента CreateComment в родительском компоненте, а затем передавать данные дочерним. Но как получить данные из нового комментария (в том виде, в котором пользователь вводит текст) в дочернем компоненте и передать обратно в родительский и дочерний? На рис. 2.12 показан пример нужного потока данных.

 

Рис. 2.12. Чтобы добавить сообщение, необходимо захватить данные из полей ввода и каким-то образом отправить их в родительский компонент. Позже обновленные данные будут использоваться для рендеринга сообщений

Как это сделать? Одним из видов данных, которые мы не рассматривали при изучении свойств, являются функции. Поскольку существует возможность передавать функции как аргументы другим функциям в JavaScript, используйте это в своих интересах. Вы можете определить метод для родительского компонента и передать его дочернему в качестве свойства. Таким образом, дочерний компонент может отправить данные обратно своему родителю, не зная, как тот будет обрабатывать данные. Если нужно изменить то, что произошло с данными, с CreateComment ничего делать не придется. Чтобы выполнить функцию, переданную в качестве свойства, дочернему компоненту нужно только вызвать метод и передать ему какие-либо данные. В следующем листинге показано, как применять функции в качестве свойств.

Листинг 2.8. Использование функций в качестве свойств

 

 

Код из листинга 2.8 доступен по адресу codesandbox.io/s/p3mk26v3lx.

Теперь, когда ваш компонент способен передать новые данные комментария родителю, нужно добавить определенную разметку, чтобы начать комментирование. В следующих главах вы будете работать с API Fetch API и RESTful JSON API, но использование некоторых элементов разметки пригодится прямо сейчас. В листинге 2.9 показано, как можно разметить некоторые базовые данные с соответствующими комментариями.

Листинг 2.9. Макетирование данных API

 

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

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

Листинг 2.10. Обработка отправки комментариев и итерация по элементам

 

 

Код из листинга 2.10 доступен по адресу codesandbox.io/s/z6o64oljn4.

На этом этапе у вас есть неприглядный, непроверенный, но функциональный компонент, который выполняет проверку свойств, состояние обновления и позволяет добавлять новые комментарии. Сделано немного, поэтому я дам вам задание — оформить окно комментариев в духе нашей вымышленной компании Letters.

2.4. Знакомство с JSX

Вы создали свой первый динамический компонент React. Если это было несложно, отлично! Если вы обнаружили, что трудно читать фрагменты кода со всеми вложенными элементами React.createElement, это тоже хорошо. Мы обсудим некоторые более простые способы создания компонентов, но сначала нужно сосредоточиться на фундаментальных принципах. Изучение остального в обратном порядке (волшебство и легкость вначале, основы и детали позже) обычно намного проще, но в итоге это может вам помешать, потому что вы не поняли, как работает основной механизм. Если взглянете на свою разметку, то вспомните цитату Сэмюэла Джонсона (Samuel Johnson), которая сейчас как нельзя более к месту: «То, что мы надеемся когда-либо делать с легкостью, сначала должны научиться делать с усердием».

2.4.1. Создание компонентов с помощью JSX

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

Что такое JSX? Это XML-подобное расширение синтаксиса для ECMAScript без какой-либо определенной семантики, предназначенной специально для использования препроцессорами. Другими словами, JSX является расширением JavaScript, похожим на XML, и предназначено оно только для применения инструментами кодирования. В любом случае это не то, что вы увидите в спецификации ECMAScript.

JSX помогает, позволяя вам писать код в стиле XML (похожем на HTML) вместо использования React.createClass. Другими словами, он позволяет вам писать код, похожий на HTML, но им не являющийся. Препроцессор JSX, такой как компилятор Babel, превращает ваш JavaScript в код, совместимый со старыми браузерами. Он анализирует весь JSX-код и преобразует его в обычный JavaScript-код. Это необходимо, так как выполнение непреобразованного JSX-кода в браузере недопустимо — при анализе JavaScript будут возникать всевозможные синтаксические ошибки.

Перспектива верстки в стиле XML HTML-подобного кода способна вас расстроить, но есть много веских причин работать с JSX, и я чуть позже расскажу про них. А пока ознакомьтесь с листингом 2.11, чтобы узнать, как выглядит компонент комментария в JSX. Я опустил часть кода, чтобы было проще сфокусироваться на синтаксисе JSX. Обратите внимание на то, что компилятор Babel добавлен в среду CodeSandbox. Как правило, вы будете использовать систему сборок типа Webpack, чтобы преобразовать JavaScript-код, также можете импортировать Babel и работать, пропустив сборку. Тем не менее это намного более медленный способ, который нельзя применять на запущенном приложении. Дополнительная информация имеется на сайте babeljs.io.

Код листинга 2.11 доступен по адресу codesandbox.io/s/vnwz6y28x5.

Листинг 2.11. Переработка компонентов с помощью JSX

 

 

2.4.2. Преимущества JSX и отличия от HTML

Теперь, увидев JSX в действии, вы, может быть, отнесетесь к нему менее скептически. Но если все еще не уверены, стоит ли с ним работать, рассмотрите ряд преимуществ, которые он дает в работе с компонентами React.

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

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

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

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

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

• Атрибутные выражения. Если вы хотите применить выражение JavaScript в качестве значения атрибута, оберните выражение в пару фигурных скобок (<Comment a={this.props.b}/>) вместо кавычек (<User a="this.props.b"/>), как показано в листинге 2.8.

• Логические атрибуты. Неуказанное значение атрибута (<Plan active />, <Input checked />) заставляет JSX рассматривать его как истинное. Чтобы передать ложное значение, вы должны использовать выражение (attribute = {false}).

• Вложенные выражения. Чтобы вложить значение выражения внутрь элемента, применяется также пара фигурных скобок (<p> {this.props.content} </ p>).

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

2.5. Резюме

Мы потратили много времени на разговор о компонентах в этой главе, поэтому вспомним некоторые ключевые моменты.

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

• Классы React получают доступ к состоянию, которое может меняться со временем (изменяемое состояние), но все элементы React получают доступ к свойствам, которые изменяться не должны (неизменяемое состояние).

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

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

• Компоненты React взаимодействуют через свойства и имеют родственные отношения. Родительские компоненты могут передавать данные потомкам, но потомки не могут изменять предков. Они могут передавать предкам данные через обратные вызовы, но не имеют прямого доступа к ним.

• JSX — это XML-подобное расширение JavaScript, которое позволяет писать компоненты намного проще и более привычным способом. Вначале может показаться странным писать то, что выглядит как HTML в JavaScript, но разметка JSX более привычна и, как правило, легче читаема, чем вызовы функции React.createElement.

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