Подтвердить что ты не робот

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

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

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

Моим текущим решением было бы изменить код github: combineReducers.js:

var finalState = mapValues(finalReducers, (reducer, key) => {
   var previousStateForKey = state[key]
   var nextStateForKey = reducer(previousStateForKey, action)
   ...
}

от

   var nextStateForKey = reducer(previousStateForKey, action)

в

   var nextStateForKey = reducer(previousStateForKey, action, state)

что позволило бы мне делать то, что мне нужно:

function reducer(state, action, root) {
   if (root.otherPart.get("isSomething")) {
      return state.set("anotherThing", true);
   }
   return state;
}

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

** ОБНОВЛЕНИЕ 5 ч. Декабрь 2018 года **

Из-за относительно высокого интереса к этому вопросу (15 голосов голосов), я добавляю свой собственный ответ ниже, надеюсь, что это поможет тем, кто ищет этот ответ.

4b9b3361

Ответ 1

Вам не нужно использовать combineReducers().

Из официальных документов Redux:

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

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

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

Спасибо @MichelleTilley за то, что он движет мыслью!

Ответ 2

Я использую Thunk до getState(), подготовьте данные из полного хранилища, а затем отправьте действие.

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

Леонардо

Ответ 3

Вы можете попытаться использовать:

Redux название-редукторы

Что позволяет получить состояние в любом месте вашего кода, например:

const localState1 = getState(reducerA.state1)
const localState2 = getState(reducerB.state2)

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

Ответ 4

вступление

Я хотел бы добавить ответ, который основан на моем опыте 3y+, а также повторяет некоторые другие ответы и комментарии выше (спасибо всем вкладчикам)

Короткий ответ

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

Детальный ответ

Применение редукторов, действий и селекторов организовано с использованием подхода Ducks. Использование Redux Thunk дает много преимуществ (благодаря Леонардо).

Если мы используем определения моего первоначального вопроса, одна "Утка" - это "одна часть государства", и она группирует следующие основные элементы:

  • Редуктор (обычно это функция с именем %duckName%, получает)
  • Действия и Thunks
  • Селекторы (которые получают состояние root)
  • Типы (type, interface, enums)

Состояние приложения - это объект. Это ключи - это имена всех "уток", которые участвуют в сокращении состояния приложения.

Редукторы должны быть как можно более тонкими, как рекомендовал Леонардо.

Все действия и Thunks можно разделить на следующие категории:

  1. Утиное действие
    • нет селекторов внутри
    • у аргументов есть вся информация, которой достаточно для самостоятельной работы
    • { type: "%actionName%", payload:... } Action object { type: "%actionName%", payload:... }
  2. Duck Thunk
    • нет внешних селекторов, но могут иметь внутренние (выбор из той же Duck)
    • отправляет одно или несколько Утиных действий.
    • могут отправлять другие Duck Thunks, но их следует избегать, так как это приводит к высокой сложности приложения.
  3. Умная утка
    • знает о существовании других Ducks, поэтому может выбрать из других уток
    • не должен посылать другим Уткам, так как в этом случае он может рассматриваться как действие приложения
  4. Действие приложения
    • возвращает действие Duck или другое действие приложения с измененными аргументами
  5. Приложение Thunk
    • есть селекторы от любой из уток
    • может отправить любой из Thunk или Action

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

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