Дмитрий: не обязательно. Можно сделать нечто подобное:
const innerReducer = (state = {}, action) => ...
const outerReducer = (state = {}, action) => {
switch(action.type) {
case: 'SOME_ACTION':
return { ...state, someField: innerReducer(state.someField, action) }
case 'OTHER_ACTION':
return { ...state, someField: innerReducer(state.someField, { type: 'NEW_SHINY_ACTION', payload: 'some' }) }
}
}
</lang>
Вы можете вызвать другой редьюсер передав туда экшен. Причем можно даже передать другой экшен, но вы должны понимать, что это не то же самое, что и диспатч: эти экшены идут прямо в редьюсер и должны быть простыми объектами с полем type. При этом не нарушается концепция редьюсера - это все еще чистая функция, без side-effects.
Дмитрий: а почему нет? При соблюдении указанных правил (чистота функции) - я не вижу проблем. Это внешний редьюсер должен соответствовать сигнатуре (state, action) => nextState. А для внутренних редьюсеров вы можете использовать любой API, например так: (state, something, otherParam) => nextState .