Разделительные редукторы, работающие с одним и тем же срезом данных в Redux

У меня есть магазин, который имеет такую ​​форму:

{
  // ...data

  user: {
    warranties: {
      W_1: ['O_1', 'O_2'],
      W_2: ['O_3', 'O_4']   
    }
  }
}

Где ключи начинаются с W_ являются гарантиями, ключи начинаются с O_ варианты.

Для каждой гарантии у меня есть один или несколько вариантов, связанных с ним, отношения в user.warranties в форме: warranty => [options],

Чтобы добиться этого, я комбинирую мои редукторы так:

rootReducer = combineReducers({
  // ...other main reducers

  user: combineReducers({
    // ...other user reducers
    warranties
  })
})

Теперь проблема заключается в том, что оба USER_WARRANTY а также USER_OPTION Действия обрабатываются одним и тем же редуктором, потому что:

  • Когда я добавляю опцию, мне нужно указать правильную запись гарантии.

  • И наоборот, когда я добавляю гарантию, мне нужно заполнить ее параметрами по умолчанию.

  • И, в конечном счете, они работают с одним и тем же фрагментом данных.

Итак warranties редуктор, должен реагировать на оба действия, выглядя так:

export default function warranties(state = {}, action) {
  switch (action.type) {
    case USER_WARRANTIES_ADD:
    // add warranty key to `user.warranties`

    case USER_WARRANTIES_REMOVE:
    // remove warranty key from `user.warranties`

    case USER_OPTIONS_ADD:
    // push option to `user.warranties[warrantyID]`

    case USER_OPTIONS_REMOVE:
    // remove option from `user.warranties[warrantyID]`

    default:
      return state
  }
}

Я хотел бы разделить это на два редуктора, warranties а также options, но все же пусть они оперируют одним и тем же фрагментом данных.

В идеале я бы тогда написал свой корневой редуктор так:

rootReducer = combineReducers({
  // ...other main reducers

  user: combineReducers({
    // ...other user reducers
    warranties: magicalCombine({
      warranties,
      options
    })
  })
})

куда magicalCombine это функция, которую мне трудно найти.


я пытался reduce-reducers, но выглядит как второй редуктор (options) никогда не достигается, и я на самом деле не уверен в этом, так как я не пытаюсь достичь плоского состояния, но на самом деле оперирую одним и тем же ключом.

1 ответ

Решение

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

rootReducer = combineReducers({
  // ...other main reducers

  user: combineReducers({
    // ...other user reducers
    warranties: (state, action) => {
      // state is state.user.warranties
      // we pass it to each reducer in turn and return the result
      state = warranties(state, action);
      return options(state, action);
    }
  })
})

использование reduReducers должно делать то же самое (я раньше этим не пользовался, но вот как это выглядит...)

rootReducer = combineReducers({
  // ...other main reducers

  user: combineReducers({
    // ...other user reducers
    warranties: reduceReducers(warranties, options)
  })
})

combineReducers from redux просто намеренно ограничен, чтобы передавать только значение свойства состояния, которое соответствует ключу в предоставленном ему объекте Redurs, это не совсем особенный другой способ. подробнее здесь.. https://redux.js.org/recipes/structuringreducers/beyondcombinereducers

Другие вопросы по тегам