Перейти к содержанию

Экшены

Почему type должен быть строкой или по крайней мере сериализуемым? Почему мои типы экшенов должны быть константами?

Как и состояние, серилизуемые экшены позволяют использовать несколько определяющих Redux особенностей, таких как отладка с помощью путешествия во времени (time travel) и запись и воспроизведение экшенов. Использование чего-то вроде Symbol как типа значений или instanceof для проверки типа экшенов сломает это. Строки — сериализуемы и хорошо себя документируют, поэтому они являются наилучшим типом для экшенов. Важно помнить, что можно использовать типы Symbols, Promises, или другие несериализуемые значения в экшенах, если экшены предназначены для мидлваров. Экшены должны быть сериализуемыми только в тех случаях, когда они фактически взаимодействуют со стором и передаются редьюсерам.

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

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

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

Обсуждения

Всегда ли редьюсеры и экшены преобразуются "один к одному"?

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

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

Обсуждения

Как я могу выполнять "побочные эффекты", такие как AJAX вызовы? Зачем нам нужны вещи типа “генераторов экшенов, “thunks” или “мидлвар” для осуществления асинхронного поведения?

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

Любое полноценное веб-приложение должно выполнять сложную логику, обычно включающую асинхронную работу, такую как AJAX запросы. Этот код уже не является чистой функцией. Такое взаимодействие с окружающим миром носит название “побочные эффекты”.

Redux вдохновлен функциональным программированием и из коробки выполнение побочных эффектов в нем не имеет места. В частности, функции редьюсера всегда должны быть чистыми функциями типа (state, action) => newState. Однако, мидлвары Redux-а позволяют перехватывать экшены и добавлять к ним сложное поведение, включая побочные эффекты.

В целом, Redux предполагает, что код с побочными эффектами должен быть частью процесса создания экшенов. Пока эта идея может быть реализуема внутри UI компонента. В большинстве случаев имеет смысл вынести эту логику в переиспользуемую функцию, тогда она может быть вызвана из нескольких мест — иначе говоря, получаем функцию-генератор экшена (action creator).

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

Другой широко применяющийся подход — Redux Saga, который позволяет Вам писать выглядящий более синхронизированным код, используя генераторы и может действовать как “фоновые потоки” или “демоны” в Redux-приложении.

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

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

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

Статьи

Обсуждения

Какой асинхронный мидлвар должен я использовать? Как вы выбираете между thunks, sagas, observables или что-то еще?

Существует достаточно много мидлвар для обеспечения асинхронных / побочных эффектов, но наиболее часто используемые следующие redux-thunk, redux-sagaи redux-observable. Это разные инструменты с разными преимуществами, недостатками и вариантами использования.

В качестве общего правила:

  • Thunks лучше всего подходят для сложной синхронной логики (особенно кода, который требует доступа ко всему состоянию хранилища Redux) и простой асинхронной логики (как базовые вызовы AJAX). С использованием async/await может быть разумно использовать thunk для некоторой более сложной логики, основанной на промисах.
  • Саги лучше всего подходят для сложной асинхронной логики и несвязанного поведение типа «фонового потока», особенно если вам необходимо слушать отправленные экшены (что нельзя сделать с помощью thunks). Они требуют знания ES6 генераторов и операторов «эффектов» «redux-saga».
  • Observables решают те же проблемы, что и саги, но полагаются на RxJS для реализации асинхронного поведения. Они требуют знакомства с RxJS API.

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

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

Статьи

Обсуждения

Должен ли я отправлять несколько экшенов подряд от одного генератора экшенов?

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

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

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

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

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

Статьи

Обсуждения