habrahabr

Книга «React в действии»

  • среда, 12 декабря 2018 г. в 00:19:07
https://habr.com/company/piter/blog/432776/
  • Блог компании Издательский дом «Питер»
  • JavaScript
  • ReactJS
  • Профессиональная литература


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

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

Отрывок. Глава 11. Интеграция Redux и React



  • Редукторы — способ Redux определить, как должно измениться состояние.
  • Применение Redux с React.
  • Преобразование Letters Social для использования архитектуры приложения Redux.
  • Добавление в приложение функциональности лайков и комментариев.

Здесь вы продолжите работу, которой занимались в предыдущей главе, чтобы создать основные элементы архитектуры Redux. Будете работать над интеграцией React с действиями и хранилищем Redux и изучите, как работают редукторы. Redux — это вариант шаблона Flux, разработанный с учетом React, он хорошо работает с однонаправленным потоком данных и API React. Хотя это не универсальный выбор, многие крупные React-приложения рассматривают Redux как один из лучших вариантов при реализации решения для управления состоянием. Последуйте их примеру и примените его к Letters Social.

Получение исходного кода

Как и прежде, вы можете получить исходный код примеров из этой главы, перейдя в репозиторий GitHub по адресу github.com/react-in-action/letters-social. Если планируете начать работу здесь самостоятельно с нуля, возьмите исходный код примеров из глав 7 и 8 (если изучили их и сами выполнили примеры) или обратитесь к ветви, относящейся к данной главе (chapter-10-11).

Помните, что каждая ветвь содержит итоговый код главы (например, chapter-10-11 содержит код, получаемый в конце глав 10 и 11). Вы можете выполнить в оболочке командной строки одну из следующих команд по своему выбору, чтобы получить код примеров из текущей главы. Если репозитория вообще нет, выполните команду:

git clone git@github.com:react-in-action/letters-social.git

Если у вас уже клонирован репозиторий, то следующую:

git checkout chapter-10-11

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

npm install

11.1. Редукторы определяют, как должно измениться состояние


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

Но что такое редукторы? Если вы до сих пор наслаждались простотой Redux, то не разочаруетесь: это всего лишь простые функции, которые имеют одну цель. Редукторы — это чистые функции, которые принимают предыдущие состояние и действие в качестве аргументов и возвращают следующее состояние. Согласно документации Redux они называются редукторами, потому что сигнатура их метода выглядит как данные, передаваемые в Array.prototype.reduce (например, [1,2,3] .reduce ((a, b) => a + b, 0).

Редукторы должны быть чистыми функциями, а это означает, что с учетом ввода они будут каждый раз выдавать один и тот же соответствующий вывод. Это контрастирует с действиями или промежуточным программным обеспечением, где получаются побочные эффекты и часто возникают вызовы API. Выполнение чего-либо асинхронного или нечистого (например, вызов Date.now или Math.random()) в редукторах — это антишаблон, который может ухудшить производительность или надежность приложения. Документы Redux содержат такой пункт: «Получив те же аргументы, он должен вычислить следующее состояние и вернуть его. Без сюрпризов. Никаких побочных эффектов. Без вызовов API. Никаких изменений. Просто расчет». Подробнее об этом см. redux.js.org/basics/reducers.

11.1.1. Форма состояния и начальное состояние


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

Вы создадите исходный файл состояния, который поможет определить форму и структуру состояния. В папке констант создайте файл с именем initialState.js.

image

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

image

11.1.2. Настройка редукторов для реагирования на входящие действия


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

Редукторы несут ответственность за расчет того, как должно измениться хранилище. В большинстве приложений у вас будет много редукторов, каждый из которых отвечает за часть хранилища. Это помогает сохранять файлы лаконично и сфокусированно. В итоге вы примените метод combineReducers, доступный в Redux, чтобы объединить редукторы в один. Большинство редукторов используют инструкцию switch со случаями для разных типов действий и команду «поймать всех» по умолчанию для всего остального, чтобы гарантировать, что неизвестные типы действий (вероятно, созданные случайно, если они есть) не повлияют на состояние.

Также редукторы делают копии состояния и не изменяют напрямую существующее состояние хранилища. Если вы посмотрите на рис. 11.1, то увидите, что редукторы используют состояние при выполнении своей работы. Такой подход аналогичен тому, как обычно работают неизменяемые структуры данных: вместо прямых изменений создаются измененные копии. В листинге 11.2 показано, как настроить редуктор загрузки. Обратите внимание на то, что в этом случае вы имеете дело с плоским срезом состояния — булевым свойством loading, поэтому просто возвращаете true или false для нового состояния. Вы часто будете работать с объектом состояния, у которого есть много ключей или вложенных свойств, в таком случае редуктору нужно будет сделать больше, чем просто вернуть true или false.

image

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

image

Затем вы создадите еще один редуктор, чтобы применить свои навыки работы с Redux. В конце концов, многие редукторы не будут просто возвращать true или false. Или по крайней мере в вычислениях будет больше того, чтобы выдать просто true или false. Другая ключевая часть приложения Letters Social показывает и создает сообщения, и нужно перенести ее в Redux. Вы должны сохранить бо'льшую часть существующей логики, используемой приложением, и перевести ее в удобную для Redux форму, как было бы, если бы вы приспосабливали реальное React-приложение для применения Redux. Создайте два редуктора для обработки самих сообщений и один — для отслеживания идентификаторов сообщений. В более крупном приложении можете объединить их вместе под другим ключом, но сейчас хорошо хранить их по отдельности. Это тоже пример того, как можно настроить несколько редукторов для обработки одного действия. В листинге 11.3 показано, как написать редуктор для комментариев. Здесь вы создадите немало редукторов, и, как только это будет сделано, приложение получит не только подробное описание событий, которые могут произойти, но и способы изменения состояния.

image

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

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

image

image

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

Миграция в Redux: нужна ли?

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

А общий результат заключался в возможности более быстрого итерационного воспроизведения продукта с помощью шаблонов, которые Redux помог нам поместить в нужное место. Через несколько месяцев после миграции Redux мы закончили серию полных переработок приложения. Несмотря на то что мы переделали большую часть React-приложения, архитектура Redux позволяла внести совсем немного изменений в управление состоянием и бизнес-логику приложения. Более того, шаблоны Redux упростили внесение добавлений в состояние приложения там, где необходимо. Интеграция Redux оправдала работы по настройке и переводу на него приложения и продолжает приносить дивиденды.
» Более подробно с книгой можно ознакомиться на сайте издательства
» Оглавление
» Отрывок

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