Redux на практике осваиваем действия в приложении


Оглавление (нажмите, чтобы открыть):

Введение в Redux и как обновляется состояние в приложении Redux

Сегодня я собираюсь поделиться несколькими основными концепциями Redux без использования какой-либо библиотеки представлений (React или Angular). Это своего рода личная заметка для дальнейшего использования, но она может помочь и другим.

Что такое Redux?

Redux — это библиотека с открытым исходным кодом для улучшения предсказуемости состояния в приложении JavaScript. Это независимая библиотека, обычно используется с другими библиотеками, такими как React и Angular, для лучшего управления состоянием приложения. Redux был создан Дэном Абрамовым в 2015 году для эффективного управления сложным состоянием.

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

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

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

Redux Store:

Как мы уже говорили ранее, основная цель Redux — обеспечить предсказуемое управление состоянием в наших приложениях. Redux достигает этого, имея единый источник правды, то есть единое дерево состояний (State Tree). State Tree — это простой объект JavaScript, который содержит все состояние нашего приложения. Есть только несколько способов взаимодействия с state. И это облегчает нам отладку или отслеживание нашего состояния.

Теперь у нас есть только одно основное состояние, которое включает все состояния приложения, расположенного в одном месте. Любые изменения, внесенные в State Tree, отражаются во всем приложении, поскольку это единственный источник данных для приложения. И это первый фундаментальный принцип Redux.

Правило № 1 — Единственный источник правды

Состояние всего вашего приложения хранится в дереве объектов в одном хранилище.

Способы взаимодействия с State Tree:

  • Получение состояния
  • Прослушивание изменений в state
  • Обновление состояния

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

Давайте поговорим о методах, которые store дает нам для взаимодействия с state.

  • getState() — возвращает текущее состояние приложения.
  • dispatch(action) — Единственный способ обновить состояние — это отправить действие и выполнить его с помощью dispatch(action) .
  • subscribe(listener) — целью этого метода является прослушивание изменений состояния. Каждый раз, когда состояние изменяется, оно вызывается и возвращает обновленное состояние.
  • replaceReducer(nextReducer) — заменяет reducer, используемый в данный момент хранилищем для вычисления состояния.

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

Обновление состояния в приложении:

Единственный способ обновить состояние — отправить action. Это второе правило.

Правило № 2 — Состояние только для чтения

Action — это простой объект JavaScript, который отслеживает конкретное событие, происходящее в приложении. Что делает его особенным, так это свойство type, которое является его необходимой частью.

Основная цель этого свойства — сообщить Redux о происходящем. Этот тип должен описывать action. Наряду со свойством type у него может быть другая информация о происходящем событии.

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

Здесь у нас есть action, чтобы добавить книгу в корзину.

Как только мы определим наш action, мы передадим его диспетчеру. store.dispatch() — это функция, предоставляемая библиотекой, которая принимает действие для выполнения action и изменения состояния. Redux ограничивает обновление состояния только этим методом.

Этот строгий способ обновления состояния гарантирует, что состояние не может быть изменено напрямую ни во view, ни любым сетевым обратным вызовом. Единственный способ обновить состояние — определить action и затем отправить его. Помните, что action — это простые объекты JavaScript. Action могут быть зарегистрированы, сериализованы и воспроизведены для целей отладки.

Теперь у нас есть store, state и action в нашем приложении для выполнения некоторых задач. Теперь нам нужен способ использовать эти action для обновления. Это можно сделать с помощью чистой функции, и это правило № 3.

Правило № 3 — Изменения сделаны с чистыми функциями

Нам нужна простая чистая функция, которая в качестве параметра принимает текущее state приложения и action, которое нужно выполнить с состоянием, а затем возвращает обновленное состояние. Эти функции называются reducer.

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

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

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

Процесс.

Если мы соединяем точки, Redux — это библиотека, в которой есть хранилище, содержащее дерево состояний и несколько методов взаимодействия с состоянием. Единственный способ обновить состояние внутри хранилища — это отправить action и определить функцию reducer для выполнения задач на основе заданных действий. После отправки action переходит в функции reducer, который выполняет задачи и возвращает обновленное состояние в хранилище. Вот что такое Redux.

Что мы тут узнали?

Давайте подведем итог тому, что мы тут узнали, чтобы подвести итоги.

  • Redux — контейнер с предсказуемым состоянием с открытым исходным кодом
  • State Tree (дерево состояний) — простой объект JavaScript, который содержит состояние всего приложения
  • Три способа взаимодействия со state:
    Store — единый блок , который содержит состояние дерева и методы для взаимодействия с деревом состояний
    Action — Javascript объект для описания действий
    Reducers — чистая Javascript функция принимающая текущее состояние и действие, чтобы вернуть новое состояние

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

Redux на практике: осваиваем действия в приложении

Название: React в действии
Автор: Марк Тиленс Томас
Издательство: Питер
Год: 2020
Формат: pdf
Страниц: 368
Размер: 53 Mb
Язык: Русский

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

Краткое руководство по Redux для начинающих

Redux — это менеджер состояний. Чаще всего его используют с React, но его возможности не ограничиваются одной этой библиотекой. Хотя в React есть собственный метод управления состояниями (почитать о нём можно в руководстве по React для начинающих), он плохо масштабируется. Перемещение состояния вверх по дереву работает для простых приложений, но в более сложных архитектурах изменение состояния производится через свойства (props). Ещё лучше делать это через внешнее глобальное хранилище.

Redux — это способ управления состоянием приложения. Он основан на нескольких концепциях, изучив которые, можно с лёгкостью решать проблемы с состоянием.

Когда нужно пользоваться Redux?

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

Простым приложениям Redux не нужен.

Использование Redux

Разберём устройство Redux и механизм его работы.

Неизменяемое дерево состояний

В Redux общее состояние приложения представлено одним объектом JavaScript — state (состояние) или state tree (дерево состояний). Неизменяемое дерево состояний доступно только для чтения, изменить ничего напрямую нельзя. Изменения возможны только при отправке action (действия).

Действия

Действие (action) — это JavaScript-объект, который лаконично описывает суть изменения:

Единственное требование к объекту действия — это наличие свойства type , значением которого обычно является строка.


Типы действий должны быть константами

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

и выносить действия в отдельные файлы. А затем их импортировать:

Генераторы действий

Генераторы действий (actions creators) — это функции, создающие действия.

Обычно инициируются вместе с функцией отправки действия:

Или при определении этой функции:

Редукторы

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

Что такое редуктор

Редуктор (reducer) — это чистая функция, которая вычисляет следующее состояние дерева на основании его предыдущего состояния и применяемого действия.

Чистая функция работает независимо от состояния программы и выдаёт выходное значение, принимая входное и не меняя ничего в нём и в остальной программе. Получается, что редуктор возвращает совершенно новый объект дерева состояний, которым заменяется предыдущий.

Чего не должен делать редуктор

Редуктор — это всегда чистая функция, поэтому он не должен:

  • мутировать аргументы;
  • мутировать состояние. Вместо этого создаётся новое состояние с помощью Object.assign(<>, . ) ;
  • иметь побочные эффекты (никаких API-вызовов с какими-либо изменениями);
  • вызывать нечистые функции. Это функции, результат которых зависит от чего-то кроме их аргументов (например, Date.now() или Math.random() ).

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

Симулятор редуктора

Упрощённо базовую структуру Redux можно представить так:

Состояние
Список действий
Редуктор для каждой части состояния
Редуктор для общего состояния

Хранилище

Хранилище (store) — это объект, который:

  • содержит состояние приложения;
  • отображает состояние через getState() ;
  • может обновлять состояние через dispatch() ;
  • позволяет регистрироваться (или удаляться) в качестве слушателя изменения состояния через subscribe() .

Хранилище в приложении всегда уникально. Так создаётся хранилище для приложения listManager:

Хранилище можно инициировать через серверные данные:

Функции хранилища

Прослушивание изменений состояния:

Поток данных

Поток данных в Redux всегда однонаправлен.

Передача действий с потоками данных происходит через вызов метода dispatch() в хранилище. Само хранилище передаёт действия редуктору и генерирует следующее состояние, а затем обновляет состояние и уведомляет об этом всех слушателей.

Redux-in-russian

Original Redux documentation with a translation into Russian

Redux является предсказуемым контейнером состояния для JavaScript приложений. (Не путайте с WordPress фреймворком – Redux Framework.)

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

Вы можете использовать Redux вместе с React или с любой другой view-библиотекой. Это крошечная библиотека (2kB, включая зависимости).

Изучите Redux

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

Только основы

Если вы новичок в Redux и хотите понять основные понятия, см:

  • Базовое руководство в документации Redux
  • Бесплатная видео-серия «Getting Started with Redux» на Egghead.io от создателя Redux Дэна Абрамова
  • Слайдшоу «Redux Fundamentals» а также список полезных ресурсов для изучения Redux от одного из разработчиков Redux — Марка Эриксона
  • Если вы лучше учитесь просматривая код и играя с ним, ознакомьтесь с нашим списком примеров Redux приложений, доступных в качестве отдельных проектов в репозитории Redux, а также в качестве интерактивных примеров на CodeSandbox.
  • Руководства по Redux в секции списка ссылок React/Redux. Вот список рекомендуемых нами учебников:
    • Посты Dave Ceddia What Does Redux Do? (and when should you use it?) и How Redux Works: A Counter-Example являются отличным введением к основам Redux и как использовать его с React, как и этот пост React and Redux: An Introduction.
    • Пост Valentino Gagliardi React Redux Tutorial for Beginners: Learning Redux in 2020 является отличным расширенным введением во многие аспекты использования Redux.
    • Статья на CSS Tricks Leveling Up with React: Redux хорошо раскрывает основы Redux.
    • Это руководство DevGuides: Introduction to Redux раскрывает различные аспекты Redux, включая экшены, редюсеры, мидлвары, использование с React.

Средний уровень

Когда вы освоите основы работы с действиями, редюсерами и хранилищем, у вас могут возникнуть вопросы по таким темам, как работа с асинхронной логикой и AJAX запросами, подключение UI фреймворка, например React, к вашему хранилищу Redux и настройка приложения для использования Redux:

  • Раздел документации «Продвинутое использование» раскрывает работу с асинхронной логикой, мидлвар, маршрутизацию.
  • Страница документации «Образовательные ресурсы» указывает на рекомендуемые статьи по различным темам, связанным с Redux.
  • Серия статей из 8 частей от Sophie DeBenedetto Building a Simple CRUD App with React + Redux показывает, как собрать базовое приложение CRUD с нуля.

Использование в реальном мире

Переход от приложения TodoMVC, к реальному production приложению, может стать большим скачком, но у нас есть много ресурсов, которые помогут:

  • Бесплатная видеосерия «Building React Applications with Idiomatic Redux» от создателя Redux Дэна Абрамова, основывается на его первой серии видео и охватывает такие темы, как мидлвары, маршрутизация и постоянство.
  • Redux FAQ отвечает на многие базовые вопросы, связанные с использованием Redux, а также секция документации «Рецепты» которая содержит информацию об обработке полученных данных, тестирование, структурирование логики редюсеров и уменьшении шаблонности.
  • Серия руководств «Practical Redux» от одного из разработчиков Redux Марка Эриксона, демонстрирует практические техники среднего и продвинутого уровня для работы с React и Redux (также доступен в виде интерактивного курса на Educative.io) —Список ссылок React/Redux содержит классифицированные статьи о работе с редюсерами и селекторами, управление сайд-эффектами, архитектуре и лучшим практикам Redux, и т.д.
  • Наше сообщество создало тысячи библиотек, дополнений и инструментов, связанных с Redux. Страница документации «Экосистема» перечисляет наши рекомендации и есть полный список, доступный в Redux addons catalog.
  • Если вы хотите учиться на реальной кодовой базе приложений, каталог дополнений также содержит список специально написанных и реальных приложений.

Наконец, Марк Эриксон проводит серию воркшопов по Redux при помощи Workshop.me. Проверьте расписание воркшопов для предстоящих дат и местоположений.

Помощь и обсуждения

Канал #redux, как часть Reactiflux Discord community, наш официальный ресурс для всех вопросов связанных с изучением и использованием Redux. Reactiflux — отличное место для того, чтобы общаться, задавать вопросы и учиться — присоединяйтесь к нам!


Прежде чем продолжить

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

Вот несколько советов о том, когда имеет смысл использовать Redux:

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

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

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

Опыт разработки

Дэн Абрамов, автор Redux, написал Redux пока работал над своим докладом на React Europe, который назывался “Hot Reloading with Time Travel”. Его целью было создание библиотеки управления состоянием с минимальным API, но вполне предсказуемым поведением, так чтобы можно было реализовать протоколирование, горячую перезагрузку, путешествия во времени, универсальные приложения, запись и воспроизведение, без каких-либо вложений от разработчика.

Влияния

Redux развивает идеи Flux, но избегает его сложности, воспользовавшись примерами из Elm. Вне зависимости от того, использовали вы их или нет, Redux занимает всего несколько минут, чтобы начать с ним работу.

Мастер Йода рекомендует:  IBM приобрела поисковую систему Blekko

Установка

Для установки стабильной версии:

Предполагается, что вы используете npm в качестве менеджера пакетов.

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

Чаще всего люди используют Redux, как набор CommonJS модулей. Эти модули — это то, что вы получаете, когда импортируете redux в Webpack, Browserify или Node окружение. Если вам нравится жить на острие технологий и использовать Rollup, мы также поддерживаем это.

Если вы не используете сборщики модулей, это тоже нормально. Npm пакет redux включает предкомпилированные UMD develop и production сборки в каталоге dist . Они могут быть использованы напрямую без бандлера и, таким образом, совместимы со многими популярными загрузчиками JavaScript-модулей и окружениями. Например, вы можете подключить UMD-сборку на страницу при помощи тэга script > или установить при помощи Bower. Сборки UMD делают Redux доступным через глобальную переменную window.Redux .

Исходные коды Redux написаны на ES2015, но мы предкомпилировали и CommonJS и UMD сборки в ES5 поэтому они работают в любом современном браузере. Вам нет необходимости использовать Babel или сборщик модулей чтобы начать пользоваться Redux.

Дополнительные пакеты

Обратите внимание, что в отличие от самого Redux, многие пакеты в экосистеме Redux не предоставляют сборки UMD, поэтому мы рекомендуем использовать сборщики модулей CommonJS, такие как [Webpack] (https://webpack.js.org/) и [Browserify] (http://browserify.org/) для наиболее комфортной разработки.

Основные принципы

Все состояние вашего приложения сохранено в объекте внутри одного хранилища (store). Единственный способ изменить дерево состояния — это вызвать действие (action), объект описывающий то, что случилось. Чтобы указать, каким образом действия преобразовывают дерево состояния, вы пишете чистые «редюсеры».

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

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

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

Изучайте Redux вместе с его создателем

Видео уроки Redux от Dan Abramov

Getting Started with Redux

Getting Started with Redux — это видео-курс, состоящий из 30 роликов созданных Дэном Абрамовым, автором Redux. Он предназначен для дополнения части документации «Основы», привнося дополнительные сведения о неизменности, тестировании, лучших практиках Redux, а также об использовании Redux с React. Данный курс является и всегда будет бесплатным.

И так, чего же вы ждете?

Посмотрите 30 бесплатных уроков «Getting Started with Redux»!

Note: Если вам понравился мой курс, подумайте о поддержке Egghead путем [покупки подписки] (https://egghead.io/pricing). Подписчики имеют доступ к исходному коду, для примера, в каждом из моих видео, а также к массе продвинутых уроков по другим темам, включая JavaScript in depth, React, Angular и многое другое. Многие [преподаватели Egghead] (https://egghead.io/instructors) также являются авторами библиотек с открытым исходным кодом, т.ч. покупка подписки — это хороший способ поблагодарить их за работу, которую они сделали.

Создание React приложений с помощью Redux

Building React Applications with Idiomatic Redux — это вторая бесплатная видео серия от Дэна Абрамова. Он продолжает темы, начатые в первой серии и охватывает практические технологии, необходимые для создания ваших приложений React и Redux: усовершенствованное управление состоянием, мидлвары, интеграция React Router и другие общие проблемы, с которыми вы, вероятно, столкнетесь при создании приложений для своих клиентов и заказчиков. Как и в первой серии, этот курс всегда будет бесплатным.

Смотрите бесплатный видео курс «Idiomatic Redux»

Практический курс Redux

Практический Redux — платный интерактивный курс одного из главных разработчиков Redux Mark Erikson. Курс предназначен для того, чтобы показать, как применять базовые концепции Redux к созданию чего-то большего, чем приложение TodoMVC. Он включает в себя такие реальные темы, как:

  • Добавление Redux к новому проекту Create-React-App и настройка Hot Module Replacement для более быстрой разработки
  • Управление вашим пользовательским интерфейсом с помощью Redux
  • Использование библиотеки Redux-ORM для управления связанными данными в вашем хранилище Redux
  • Создание главного/детального представления для отображения и редактирования данных
  • Написание специальной усовершенствованной логики редюсера Redux для решения конкретных задач
  • Оптимизация производительности подключенных к Redux полей формы

И многое другое!

Курс основывается на оригинальной бесплатной учебной серии «Практический Redux», но с обновленным и улучшенным контентом.

Воркшопы Redux

Марк Эриксон — один из разработчиков Redux Mark Erikson совместно с Workshop.me проводит серию воркшопов по Redux

  • История и цель Redux
  • Редюсеры, действия и работа с хранилищем Redux
  • Использование Redux с React
  • Использование и написание мидлвар для Redux
  • Работа с вызовами AJAX и другими побочными эффектами
  • Тестирование приложений Redux
  • Реальная структура и разработка приложений Redux

Документация

Для экпорта в PDF, ePub MOBI или чтения в оффлайн и инструкциям, как это можно осуществить, обратите внимание на: paulkogel/redux-offline-docs.

Для документации в Offline, пожалуйста посмотрите: devdocs

Примеры

Почти все примеры имеют соответствующую песочницу CodeSandbox. Это интерактивная версия кода, с которой вы можете играть онлайн.

Если вы новичок в экосистеме NPM и имеете проблемы с получением и запуском проекта или не уверены, куда вставить шаблон, попробуйте simplest-redux-example который использует Redux вместе с React и Browserify.

Отзывы

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

  • The Elm Architecture за великолепное введение в моделирование обновления состояния посредством редюсеров;
  • Turning the database inside-out за взрыв моего сознания;
  • Developing ClojureScript with Figwheel за убеждение меня в том, что переоценка должна «просто работать»;
  • Webpack за Hot Module Replacement;
  • Flummox за обучение меня подходу Flux без шаблонов или синглетонов;

  • disto за доказательство концепции «hot reloadable» хранилищ;
  • NuclearJS за доказательство того, что такая архитектура может быть производительной;
  • Om за популяризацию идеи одного атома состояния;
  • Cycle за демонстрацию того, как часто функция является лучшим инструментом;
  • React за прагматические инновации.

Особенная благодарность Jamie Paton за передачу прав на redux NPM пакет.

Вы можете найти официальное лого на GitHub.

История изменений

Это проект придерживается принципов семантического версионирования. Каждый релиз, вместе с инструкциями миграции, документированы на странице релизов Github.

Меценаты

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

Начало работы с Redux: учимся на примере

Russian (Pусский) translation by Ilya Nikov (you can also view the original English article)

Redux помогает вам управлять состоянием, устанавливая состояние на глобальном уровне. В предыдущем уроке мы подробно рассмотрели архитектуру Redux и ее неотъемлемые компоненты, такие как действия, создатели действий, хранилище и редукторы.

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

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

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

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

  • показать все контакты
  • поиск контактов
  • получить все контакты с сервера
  • добавить новый контакт
  • отправить новые контактные данные на сервер

Вот как будет выглядеть наше приложение:

Конечный продукт — Список контактов

Конечный продукт — Добавить контакт

Охватить все за один раз сложно. Итак, в этом посте мы сосредоточимся только на части Redux, добавив новый контакт и отобразив новый добавленный контакт. С точки зрения Redux мы будем инициализировать состояние, создавать хранилище, добавлять редукторы и действия и т.д.

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

Создаем эскиз дерева состояний

Вы можете скачать демо-приложение Reaction-redux из моего репозитория GitHub. Клонируйте репо и используйте ветку v1 в качестве отправной точки. Ветвь v1 очень похожа на шаблон create-react-app. Разница лишь в том, что я добавил несколько пустых каталогов для организации Redux. Вот структура каталогов.

Кроме того, вы можете создать новый проект с нуля. В любом случае, вам нужно будет установить базовый react и redux, прежде чем вы сможете начать.

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

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

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

Как организовать Redux

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

Самым распространенным шаблоном, который вы найдете, является структура файлов и папок в стиле Rails. У вас будет несколько каталогов верхнего уровня, подобных приведенным ниже:

  • components: место для хранения немых компонентов React. Этим компонентам все равно, используете ли вы Redux или нет.
  • containers: каталог для компонентов Smart React, которые отправляют действия в хранилище Redux. Здесь будет происходить связь между redux и react.
  • actions: создатели действий перейдут в этот каталог.
  • reducers: каждый редуктор получает отдельный файл, и вы разместите всю логику редуктора в этом каталоге.
  • store: логика для инициализации состояния и настройки хранилища будет здесь.

Изображение ниже демонстрирует, как может выглядеть наше приложение, если мы будем следовать этому шаблону:

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

А пока давайте создадим каталоги для components, containers, store, reducers и action. Начнем со store.

Одно хранилище, несколько редукторов

Давайте сначала создадим прототип для store и reducer. Из нашего предыдущего примера, вот как будет выглядеть наш store:

У оператора switch есть три случая, которые соответствуют трем действиям, которые мы будем создавать. Вот краткое объяснение того, для чего предназначены действия.

  • HANDLE_INPUT_CHANGE : Это действие запускается, когда пользователь вводит новые значения в форму контакта.
  • ADD_NEW_CONTACT : это действие отправляется, когда пользователь отправляет форму.
  • TOGGLE_CONTACT_FORM : это действие пользовательского интерфейса, которое позволяет показать/скрыть контактную форму.

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

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

Чтобы устранить проблему с одним редуктором, в Redux есть метод combReducers, который позволяет создавать несколько редукторов, а затем объединять их в одну редукционную функцию. Функция combReducers улучшает читаемость. Поэтому я собираюсь разделить редуктор на две части: contactsReducer и uiReducer .

В приведенном выше примере createStore принимает необязательный второй аргумент, который является начальным состоянием. Однако, если мы собираемся разделить редукторы, мы можем переместить весь initialState в новое местоположение файла, скажем, redurs / initialState.js. Затем мы импортируем подмножество initialState в каждый файл редуктора.

Расщепление редуктора

Давайте реструктурируем наш код, чтобы исправить обе проблемы. Сначала создайте новый файл с именем store/createStore.js и добавьте следующий код:

Затем создайте корневой редуктор в reducers/index.js следующим образом:

Наконец, нам нужно создать код для contactsReducer и uiReducer .

reducers/contactsReducer.js

reducers/uiReducer.js

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

Поскольку мы рассмотрели много кода, давайте посмотрим на изменения, которые мы внесли в наш подход:


  1. Был введен вызов combineReducers , чтобы связать редукторы.
  2. Состояние объекта ui будет обрабатываться uiReducer , а состояние контактов — contactReducer .
  3. Для поддержания чистоты редукторов были использованы операторы спреда. Синтаксис из трех точек является частью оператора распространения. Если вас не устраивает такой синтаксис, вам следует рассмотреть возможность использования библиотеки, такой как Immutability.js.
  4. Начальное значение больше не указывается в качестве необязательного аргумента для createStore . Вместо этого мы создали для него отдельный файл с именем initialState.js. Мы импортируем initialState и затем устанавливаем состояние по умолчанию, выполняя state=initialState.ui .

Инициализация состояния

Вот код для файла reducers/initialState.js.

Действия и создатели действий

Давайте добавим пару действий и создателей действий для добавления обработки форм, добавления нового контакта и переключения состояния пользовательского интерфейса. Если вы помните, создатели действий — это просто функции, которые возвращают действие. Добавьте следующий код в action/index.js.

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

В нашем случае мы создали три действия.

TOGGLE_CONTACT_FORM не нуждается в полезной нагрузке, потому что каждый раз, когда действие запускается, значение ui.isContactFormHidden переключается. Булевозначные действия не требуют полезной нагрузки.

Действие HANDLE_INPUT_CHANGE запускается при изменении значения формы. Так, например, представьте, что пользователь заполняет поле электронной почты. Затем действие получает «email» и «bob@example.com» в качестве входных данных, а полезная нагрузка, передаваемая редуктору, представляет собой объект, который выглядит следующим образом:

Редуктор использует эту информацию для обновления соответствующих свойств состояния newContact .

Рассылка действий и подписка на хранилище

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

  • dispatch(action) : отправляет действие, которое потенциально может вызвать изменение состояния.
  • getState() : возвращает текущее дерево состояний вашего приложения.
  • subscriber(listener) : слушатель изменений, который вызывается каждый раз, когда отправляется действие и изменяется некоторая часть дерева состояний.

Перейдите в файл index.js и импортируйте функцию configureStore и три действия, которые мы создали ранее:

Затем создайте объект store и добавьте прослушиватель, который регистрирует дерево состояний каждый раз при отправке действия:

Наконец, отправьте несколько действий:

Если все работает правильно, вы должны увидеть это в консоли разработчика.

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

Заключение

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

Redux: шаг за шагом

никаких деревьев, только камни

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

Продуманная методология для идиоматического Redux

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

Какой подход верный? Единственного и четкого ответа нет. И нет «лучшего» пути использования Redux. Стоит признать, что большой выбор подходов заводит в тупик. Я хочу продемонстрировать свой личный вариант использования библиотеки. Он понятный, применимый к самым разнообразным сценариям из жизни и, что самое главное, он прост в освоении.

Итак, пора создать наше приложение!

Для продолжения нам нужен реальный пример. Давайте создадим приложение, показывающее самые популярные посты с Reddit.

На первом экране мы выясним у пользователя три наиболее интересные для него темы. После того, как пользователь сделает выбор, будем показывать список постов по выбранным темам (все посты либо посты по конкретной теме). По клику на пост в списке будем показывать его содержание.

Установка

Поскольку мы используем React, то для начала работы возьмем Create React App — официальный стартовый шаблон. Также установим redux, react-redux и redux-thunk. Результат должен быть похож на этот.

Давайте изменим index.js и создадим в нем стор, подключим санки:

Одна из главных вещей, которая часто упускается в различных Redux туториалах: а где же место Redux в этом цикле? Redux является реализацией Flux-архитектуры — паттерна для организации передачи данных в React-приложениях.

В классическом Flux для хранения стейта приложения используется стор. Диспатчинг ( передача) экшенов вызывает изменение этого стейта. После этого происходит перерендер представления в соответствии с измененным стейтом:

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

Мастер Йода рекомендует:  Как создать макет iPad

Одна из сложностей в понимании работы Redux — это множество неочевидных терминов типа редюсеров, селекторов и санков. Для более четкого понимания взглянем на расширенный Flux-цикл. Это просто различные Redux-инструменты:

Как вы могли заметить другие Redux-инструменты типа миддлваров или саг не показаны. Это сделано намеренно, эти инструменты не играют существенной роли в нашем приложении.

Файловая структура проекта

Создадим корневую папку /src и в ней следующие подкаталоги:

  • /src/components — «глупые» React-компоненты, несвязанные с Redux
  • /src/containers — «умные» React-компоненты, подключаемые к Redux-стору
  • /src/services — некоторые абстракции для внешнего API (например, для бекенда)
  • /src/store — весь специфичный для Redux код находится здесь, включая всю бизнес-логику нашего приложения

Папка store в свою очередь состоит из доменов, которые содержат:

  • /src/store//reducer.js — редюсеры, экспортируемые по умолчанию, и селекторы, экспортируемые с помощью именованного экспорта
  • /src/store//actions.js — все обработчики экшенов домена (санки и простые объекты)

State-first подход

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

Итак, какой стейт приложения требуется для первой стадии?

Нам нужно будет сохранить список тем, полученных с сервера. Также нужно будет сохранить id выбранных пользователем тем (максимум три id). Будет нелишним сохранить порядок выбора. Например, если, в нашем случае, уже выбрано три темы и пользователь выбирает ещё, то мы будем удалять самую старую из выбранных тем.

Каким образом будет стуктурно организован стейт приложения? В моей предыдущей статье есть список полезных советов — Avoiding Accidental Complexity When Structuring Your App State. Руководствуясь этими советами, мы получим следующую структуру:

URL каждой темы будет служить уникальным id.

Где мы будем хранить этот стейт? В Redux есть редюсер ( reducer) — это конструкция, хранящая стейт и обновляющая его. Так как наш код будет организован по доменам, то редюсер будет лежать в: /src/store/topics/reducer.js .

Я подготовил шаблон для создания редьюсера, вы можете посмотреть на него здесь. Обратите внимание, что для обеспечения иммутабельности нашего состояния (как того требует Redux), я выбрал библиотеку seamless-immutable.

Наш первый сценарий

После моделирования стейта, мы готовы продолжить реализовывать наше приложение. Давайте создадим компонент, выводящий на экран список тем, как только они появляются. Этот компонент будет подключен к редюсеру, а это означает, что компонент «умный», то есть он использует Redux. Создадим его в /src/containers/TopicsScreen.js .

Шаблон для создания умного компонента можно найти здесь. Также нам будет нужно вызвать его внутри корневого компонента App. Теперь, когда всё настроено, попробуем получить несколько тем с сервера Reddit.

Правило: умные компоненты не должны содержать никакой логики, кроме передачи действий (диспатчинг экшенов ).


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

Для удобства работы с API Reddit мы создадим новый сервис, получающий актуальное состояние сети. Это асинхронный метод и для него мы будем использовать await . Мне нравится async/await API, по этой причине я уже давно не использую промисы.

Сервис возвращает нам массив, но наше приложение хранит список тем в виде map . Тело экшена — это хорошее место для преобразования массива в map . Чтобы сохранить данные в сторе, мы должны вызвать наш редьюсер, передав в него объект — TOPICS_FETCHED .

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

Несколько слов о сервисах

Как уже отмечалось ранее, сервисы используются для работы с внешним API, в большинстве случаев с сервер-API, как API Reddit. Плюс от использования сервисов в том, что наш код становится более независимым от изменений API. Если в будущем Reddit решит что-то изменить (конечную точку, названия полей), то эти изменения затронут только наши сервисы, а не всё приложение целиком.

Правило: cервисы должны быть stateless (то есть не должны иметь состояния).

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

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

Реализация сервиса довольно проста, увидеть её можно здесь.

Завершение сценария — редюсер и представление

Объект TOPICS_FETCHED , содержащий только что полученный список тем topicsByUrl , передается, как аргумент в редюсер. Редюсер не должен делать ничего, кроме сохранения этих данных в стейте:

Обратите внимание на использование seamless-immutable . Эта библиотека применяется для того, чтобы сделать наше изменение явным и понятным. Использование таких библиотек не является обязательным, я предпочитаю использовать прием со спред-оператором.

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

Я решил, что наше представление будет отображать список тем с помощью отдельного компонента ListView , принимающего пропсы rowsById и rowsIdArray . Внутри TopicsScreen я использую mapStateToProps для обработки этих пропсов (далее они будут передаваться непосредственно в ListView ). Пропсы могут быть получены из нашего стейта. Обратите внимание, что я не обращаюсь к стейту напрямую.

Правило: умные компоненты должны обращаться к состоянию только с помощью селекторов.

Селекторы один из самых главных инструментов Redux, про который обычно забывают. Селектор — это чистая функция, принимающая в качестве аргумента глобальный стейт и возвращающая его в преобразованном виде. Селекторы тесно связаны с редюсерами и расположены внутри reducer.js . Селекторы позволяют нам провести некоторые расчеты по данным, прежде чем данные попадут в представление. В будущем мы воспользуемся этим приёмом. Каждый раз, когда нам необходимо получить часть стейта (например в mapStateToProps ), мы должны использовать селекторы.

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

Сейчас topics/reducer.js выглядит так:

Текущую стадию нашего приложения, включая ListView , можно увидеть здесь.

Несколько слов о глупых компонентах

ListView хороший пример глупого компонента. Он не подключен к стору и не использует Redux. В отличие от умных компонентов, глупые расположены в /src/components .

Глупые компоненты получают данные от родителя через пропсы и могут хранить локальный стейт.

Итак, когда же нам надо переходить от умного компонента к глупому?

Правило: вся логика представления в умных компонентах должна выноситься в глупые.

Если вы посмотрите на реализацию ListView, то вы можете увидеть некоторые скрипты представления, например итерацию строк. Мы должны избегать написания такой логики внутри умного TopicsScreen. Такой подход позволяет пользоваться умными компонентами только как прослойками. Другой плюс такого подхода в том, что ListView становится переиспользуемым.

Следующий сценарий — выбор нескольких тем

Первый сценарий завершен. Переходим к следующему: пользователь может выбрать только три темы из списка.

Сценарий запускается, когда пользователь кликает по одной их тем. Это событие отлавливается в TopicsScreen , но так как умный компонент не может содержать никакой бизнес-логики, то мы должны диспатчить новый экшен — selectTopic . Этот экшен тоже будет реализован с помощью санка, разместим его в topics/actions.js . Как вы могли заметить, почти каждый экшен, который мы экспортируем (для диспатчинга), — это санк.

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

Нам нужно будет обновить редюсер таким образом, чтобы он мог обрабатывать TOPICS_SELECTED и сохранять новые выбранные темы. Возникает вопрос, а должен ли selectTopic быть санком? Ведь мы можем сделать selectTopic простым объектом действия и передать его внутрь редюсера. Это тоже правильный подход. Лично я предпочитаю хранить бизнес-логику в санках.

Обновив стейт, нам нужно вернуть список тем в наше представление. Это значит, что нужно добавить выбранные темы в mapStateToProps . Поскольку представление должно каждый раз запрашивать, выбран ли rowId или нет, то более разумным будет предавать эти данные в виде map . Так как данные будут проходить через селектор в любом случае, то именно там мы и выполним преобразование в map .

Реализуем вышеизложенную идею и добавим смену цвета фона при выборе темы внутри нового глупого компонента — ListRow . На этом этапе разработки наше приложение выглядит так.

Несколько слов о бизнес-логике

Один из принципов хорошей методологии является разделение представления и бизнес-логики. Где на данный момент у нас реализована бизнес-логика?

Вся бизнес-логика находится в папке src/store/ . Большая часть реализована в виде санков в actions.js и часть реализована внутри селекторов в reducer.js . Фактически, из этого следует правило:

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

Переход к следующей стадии — список постов

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

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

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

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

Экран постов — снова state-first

Поскольку мы теперь хорошо разбираемся в методологии, мы можем немного ускорить реализацию второй стадии. Стадия работает с новым подкаталогом — posts . Чтобы сохранить модульность нашего приложения, создадим для posts новый редюсер и новый стейт.

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

И создаем новый редюсер здесь.

Первый сценарий — список постов без фильтрации

Наш стейт готов! Теперь реализуем упрощенную версию сценария без фильтра.

Нам нужен умный компонент для отображения постов, назовем его PostsScreen , также нам нужно будет диспатчить новый экшен fetchPosts , когда у компонента будет вызван componentDidMount . Экшен будет санком, создадим его в posts/actions.js .

Это все очень похоже на то, что мы делали ранее. Реализация, по традиции, здесь.

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

Впрочем, ничего нового: реализация на месте.

Следующий сценарий — фильтр постов

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

Особый интерес для нас представляет фильтрация списка постов. В стейте приложения мы сохраняем данные в виде postsById и currentFilter . Из этих данных можно получить отфильтрованный результат, поэтому сохранять в стейте приложения мы его не будем. Бизнес логика будет запускаться в селекторе перед передачей в представление в mapStateToProps . Следовательно, селектор будет выглядеть так:

Полная реализация этого шага здесь.

Последний сценарий — содержание поста

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

Все готово


Код выше завершает реализацию нашего приложения. Полная версия приложения доступна на GitHub: https://github.com/wix/react-dataflow-example.

Какие выводы мы сделали:

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

Помните, что Redux предоставляет большое поле для экспериментов. Существуют подходы отличные от того, что использовали мы. У меня есть друзья, предпочитающие использовать redux-promise-middleware вместо санков и писать бизнес-логику только в редюсерах.

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

Redux на практике: осваиваем действия в приложении

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

В данной статье мы рассмотрим простой алгоритм подключения Redux к React-приложению, и последующей работы с ним.

Мы разберем каким образом подключить Redux к приложению, а также – где, когда и в какой последовательности использовать Actions, Reducers и Dispatchers.

Для простоты понимания, сначала мы произведем все необходимые действия в одном JavaScript файле, затем разобьём получившийся код на несколько файлов, т.е. создадим начальную структуру приложения. И в конце всего подключим полезный пакет react-redux, который позволит значительно упростить работу с Redux.

Часть 1

1. Подготовка

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

Стартовый шаблон приложения можно скачать по ссылки из репозитория проекта.

Разберем более подробно необходимый минимум для работы нашего приложения.

В файле package.json содержится несколько пакетов, которые обеспечат корректное функционирование приложения:

  • babel-preset-react – преобразует код JSX в обычный JS
  • babel-preset-es2015 – преобразует синтаксис ES6 в ES5
  • babelify & watchify – вспомогательные тулзы для наблюдения за файлами и работы babel
  • live-server – простой сервер для нашего приложения с автообновлением
  • concurrently – одновременный запуск нескольких npm команд

Ну и самое главное, в файле src/index.html мы просто подключим библиотеки React & Redux по ссылке – всё как в старые добрые времена ��

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

Добавим в файл src/app.js начальный код для проверки работоспособности нашего приложения:

Запустим приложение командой npm start , и если все было установлено правильно, то в браузере появится приветствие, созданное с помощью React.

2. Создаем Store

Первым делом создадим хранилище, которое будет общим для всего приложения:

Специально для целей объединения нескольких редукторов, мы используем метод Redux .combineReducers() , который произведет все необходимые действия.

3. Создаем Reducer

Затем создадим редуктор posts :

Каждый редуктор принимает следующие параметры:

  1. state – состояние данных (posts) приложения в момент обращения к редуктору
  2. action – действие, при котором происходит обращение к редуктору

И возвращает или новое состояние данных, или состояние данных приложения по умолчанию.

4. Создаем Action Creators

Создадим Action Creators с именем addPost и действием ADD_POST :

Action Creators вернет объект с типом действия и любыми дополнительными данными, которые нам нужны.

5. Создаем дочерний компонент

Дочерний компонент нам понадобится для наглядной демонстрации Dispatchers и работы с действиями. Для начала изменим основной компонент, чтобы он смог вывести дочерний:

Затем создадим дочерний компонент, который, к примеру, будет отвечать за вывод постов:

6. Запускаем приложение

Данное решение является временным, в третьей части, когда мы подключим пакет react-redux , мы избавимся от функции run() :

В данном случае, при каждом изменении store, будет запускаться run() функция и в компонент Content передадутся актуальные данные.

Сейчас наш дочерний компонент Content не имеет прямого доступа к store. Поэтому мы передаем в него свойство addPost , которое, по сути, является функций Dispatcher для инициализации Action Creator addPost . В самом же дочернем компоненте, мы вызываем этот Dispatcher в методе createPost() :

И передаем в него объект со свойством text , значение которого берется из текстового поля.

Часть 2

7. Разбиваем приложение на файлы

Для начала уберем из index.html подключение React и Redux:

Затем установим с помощью npm пакеты react , react-dom и redux :

Создадим файл src/actions.js и поместим в него код Action Creators из файла app.js. Сейчас это только одна функция addPost() :

Теперь переместим редуктор в файл src/reducers.js :

Далее нам нужно поместить компоненты в разные файлы. Начнем с компонента App . Создадим файл src/components/App.js и поместим в него код нашего компонента:

И дочерний компонент переместим в файл src/components/Content.js :

И конечно же не забудем подключить созданные файлы и нужные модули в файле src/app.js :

Часть 3

8. Подключаем пакет react-redux

По своей сути, react-redux предоставляет удобную реализацию доступа компонентам к store и работы с actions.

Для начала установим этот пакет:

Теперь в файле src/app.js подключим этот пакет и обернем компонент нашего приложения специальным компонентом Provider , который предоставляется react-redux :

В качестве параметра, компонент Provider принимает наше store.


Теперь дочерний компонент Content может получить прямой доступ к store.

9. Импортируем нужные модули

В файле src/component/Content.js внесем изменения:

Метод connect() поможет определить, какие свойства и действия будут у нашего компонента, а также связать компонент и store.

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

10. Определяем свойства и действия для компонента

Функция mapStateToProps() определяет, какие свойства будут связаны между store и компонентом.

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

11. Связываем всё вместе

С помощью метода connect() связываем свойства и действия с нашим компонентом:

Метод connect() определяет, какие свойства и действия будут у нашего компонента.

12. Завершение

Итак, настало время подвести итог.

Краткий алгоритм работы с React & Redux будет следующим:

  • Cоздаем:
    1. Store
    2. Reducers
    3. Action Creators
  • Подключаем:
    1. Пакет react-redux
    2. Оборачиваем приложение компонентом Provider из этого пакета
    3. Передаем в Provider наше store
  • В компоненте, где нужен доступ к store подключаем:
    1. Метод connect() из пакета react-redux
    2. Созданные нами Action Creators
  • Создаем функции:
    1. mapStateToProps() – для свойств
    2. mapDispatchToProps() – для действий
  • Связываем:
    1. С помощью метода connect() наш компонент и созданные выше две функции

При создании статьи были использованы следующие источники:

CHESTUDIO

Блог компании

11 советов для тех, кто использует Redux при разработке React-приложений.

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

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

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

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

Но тут подкралось будущее.

Через пару месяцев работы над приложением в него было добавлено более 15 новых возможностей. После этого проект вышел из-под контроля. Код, в котором использовалась библиотека Redux, стало очень тяжело поддерживать. Почему так случилось? Разве поначалу не казалось, что проект ожидает долгая и безоблачная жизнь?

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

Библиотека Redux, если правильно использовать её в больших проектах, помогает, по мере роста таких проектов, сохранять их код в поддерживаемом состоянии.

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

1. Не размещайте код действий и констант в одном месте

Вы могли столкнуться с некоторыми руководствами по Redux, в которых константы и все действия размещают в одном и том же месте. Однако подобный подход, по мере роста приложения, быстро может привести к появлению проблем. Константы нужно хранить отдельно, например, в ./src/constants . В результате для поиска констант придётся заглядывать лишь в одну папку, а не в несколько.

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

Предположим, вы разрабатываете аркадную или ролевую игру и создаёте классы warrior (воин), sorceress (волшебница) и archer (лучник). В такой ситуации добиться высокого уровня поддерживаемости кода можно, организовав действия следующим образом:

Гораздо хуже будет, если всё попадёт в один файл:

Если приложение становится очень большим, то, возможно, ещё лучше будет воспользоваться примерно такой структурой разбиения кода по файлам:

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

Вот как может выглядеть действие из файла src/actions/sorceress/skills для объекта sorceress :

Вот содержимое файла src/actions/sorceress/equipping :

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

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

2. Не размещайте код редьюсеров в одном месте

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

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

3. Используйте информативные имена переменных

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

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

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

Я взялся бы на спор доказать то, что вы в таких случаях встречались с так называемым «грязным кодом».

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

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

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

Я поискал в коде по словам info , dataToSend , dataObject , и по другим, которые, в моём представлении, связаны с данными, получаемыми с сервера. Через 5-10 минут мне удалось найти код, ответственный за работу с нужными мне данными. Объект, в котором они оказывались, был назван paymentObject . В моём представлении объект, имеющий отношение к платежам, может содержать нечто вроде CVV-кода, номера кредитной карты, почтового индекса плательщика, и другие подобные сведения. В обнаруженном мной объекте было 11 свойств. Лишь три из них имели отношение к платежам: метод оплаты, идентификатор платёжного профиля и список кодов купонов.

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

Короче говоря, рекомендуется воздерживаться от использования непонятных имён для функций и переменных. Вот пример кода, в котором имя функции notify не раскрывает её смысла:

4. Не изменяйте структуры данных или типы в уже настроенных потоках данных приложений

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

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

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


5. Используйте сниппеты

Раньше я был фанатом редактора Atom, но перешёл на VS Code из-за того, что этот редактор, в сравнении с Atom, оказался невероятно быстрым. И он, при его скорости, поддерживает огромное количество самых разных возможностей.

Если вы тоже пользуетесь VS Code — рекомендую установить расширение Project Snippets. Это расширение позволяет программисту создавать собственные сниппеты для каждого рабочего пространства, используемого в некоем проекте. Это расширение работает так же, как и встроенный в VS Code механизм Use Snippets. Разница заключается в том, что при работе с Project Snippets в проекте создают папку .vscode/snippets/ . Выглядит это так, как показано на следующем рисунке.

6. Создавайте модульные, сквозные и интеграционные тесты

По мере роста размеров приложения программисту становится всё страшнее редактировать код, который не покрыт тестами. Например, может случиться так, что некто отредактировал код, хранящийся в src/x/y/z/ , и решил отправить его в продакшн. Если при этом внесённые изменения влияют на те части проекта, о которых программист не подумал, всё может закончиться ошибкой, с которой столкнётся реальный пользователь. Если в проекте имеются тесты, программист узнает об ошибке задолго до того, как код попадёт в продакшн.

7. Проводите мозговые штурмы

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

А зачем, кстати, вообще проводить мозговые штурмы в ходе разработки приложений?

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

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

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

8. Создавайте макеты приложений

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

Moqups — это одно из средств для создания макетов приложений, о котором мне часто приходится слышать. Это — быстрый инструмент, созданный средствами HTML5 и JavaScript и не предъявляющий особых требований к системе.

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

9. Планируйте поток данных в приложениях

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

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

10. Используйте функции доступа к данным

По мере роста размеров приложения растёт и количество его компонентов. А когда растёт количество компонентов, то же самое происходит и с частотой использования селекторов (react-redux ^v7.1) или mapStateToProps . Предположим, вы обнаруживаете, что ваши компоненты или хуки часто обращаются к фрагментам состояния в различных частях приложения с использованием конструкции наподобие useSelector((state) => state.app.user.profile.demographics.languages.main) . Если так — это значит, что вам нужно подумать о создании функций доступа к данным. Файлы с такими функциями стоит хранить в общедоступном месте из которого их могут импортировать компоненты и хуки. Подобные функции могут быть фильтрами, парсерами, или любыми другими функциями для трансформации данных

Вот несколько примеров.

Например, в src/accessors может присутствовать такой код:

Вот версия с использованием connect , которая может быть расположена по пути src/components/ViewUserLanguages :

Вот версия, в которой применяется useSelector , находящаяся по адресу src/components/ViewUserLanguages :

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

11. Управляйте потоком данных в свойствах с помощью деструктурирования и синтаксиса spread

Каковы преимущества использования конструкции props.something перед конструкцией something ?
Вот как это выглядит без использования деструктурирования:

Вот — то же самое, но уже с использованием деструктурирования:

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

Возможно, раньше вы видели что-то подобное следующему примеру:

Подобные конструкции непросто читать, но это — не единственная их проблема. Так, здесь имеется ошибка. Если приложение выводит и дочерние компоненты, то props.children отображается на экране дважды. Если работа над проектом ведётся в команде и члены команды недостаточно внимательны, вероятность возникновения подобных ошибок довольно-таки высока.
Если вместо этого деструктурировать свойства, то код компонента окажется понятнее, а вероятность возникновения ошибок снизится:

Итоги

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

HI-MEDIA.RU — Портал хорошего настроения

React в действии (2020) PDF

Автор: colt ; Добавлено: 13-05-2020, 17:50; Просмотров: 281; Комментариев: 0

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

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

Название: React в действии
Год издания: 2020
Автор: Марк Тиленс
Жанр: Программирование
Количество страниц: 368
Формат: PDF
Язык: Русский
Размер: 53 Mb

Redux + React: основы

Redux является предсказуемым контейнером состояния для JavaScript приложений. Это позволяет вам создавать приложения, которые ведут себя одинаково в различных окружениях (клиент, сервер и нативные приложения), а также просто тестируются.

Redux решает проблему управления состоянием в приложении, предлагая хранить данные в глобальном State, и централизованно изменяя его.

  • Компоненты формируют события (actions).
  • Reducer — модуль логики, который обрабатывает
    listeners и изменяет state.
  • State общий для всех компонентов.
  • Reducer + State = Store.
  • Компоненты обновляются при изменении state.

Установка

Reducer

Это функция, которая принимает на вход команды и изменяет state. Если тип action неизвестен, возвращаем state. Пример реализации на JavaScript:

Redux-store

Store содержит всё дерево состояний приложения. Единственный способ изменить состояние внутри него — отправить на него action.

createStore(reducer)

Store — это не класс. Это просто объект с несколькими методами. Чтобы создать его, передайте свою функцию в createStore

getState()

Возвращает текущее дерево состояний вашего приложения. Он равен последнему значению, которое возвращает store’s reducer.

dispatch(action)

store.dispatch(action) — отправляет команду, и это единственный способ вызвать изменение состояния store.

Store’s reducer будет вызываться с текущим getState() результатом и заданным action, синхронно. Его возвращаемое значение будет считаться следующим состоянием. Он будет возвращен с новым getState(), и слушатели изменений будут немедленно уведомлены.

subscribe(listener)

Добавляет слушателя изменений. Вызывается каждый раз, когда store может быть изменён.

Как это работает вместе

Actions Creators

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

bindActionCreators()

Превращает объект, значения которого являются actions creators, в объект с теми же ключами, но с каждым action creator, заключенным в dispatch-вызов, чтобы их можно было вызывать напрямую.

Единственный вариант использования для bindActionCreators- это когда вы хотите передать actions creators в компонент, который не знает о Redux, и вы не хотите передавать dispatch или хранить Redux в нем.

Структура проекта

Если у много actions creators, разумно вынести их в отдельный файл, или папку. То же касается Reducer’а.

React-Redux

Provider

connect()

connect — это компонент высшего порядка (HOC), который создаёт новые компоненты.

Мастер Йода рекомендует:  Интересное на GitHub Алгоритм поиска Bing от Microsoft
Добавить комментарий