0

I would like to merge two reducers, the first being created as a generic one and the second one would be more specific to it's own state. Both these reducers would not handle the same cases. This would help as I would only test the generic one once.

In case you were thinking about reduceReducers or combineReducers, that seems to not work since I have many "special" reducers with every one of them having the same action type to handle and all of those reducers have a different part of the state to modify.

const initialState = {
  byId : {},
  ids: []
}

const dogsReducer = ({ dogs: state = initialState, ...restOfState }, action) => {
  switch (action.type) {
    case INITIALIZE:
      return {
        byId : _.keyBy(state.dogs, 'id'),
        ids: state.map(({id}) => id)
      }
    case RESET:
      return initialState
    case SPECIFIC_DOG_ACTION:
      ...
    default:
      return state
  }
}

const catsReducer = ({ cats: state = initialState, ...restOfState}, action) => {
  switch (action.type) {
    case INITIALIZE:
      return {
        byId : _.keyBy(state, 'id'),
        ids: state.map(({id}) => id)
      }
    case RESET:
      return initialState
    case SPECIFIC_CAT_ACTION:
      ...
    default:
      return state
  }
}

I want to isolate the following cases : INITIALIZE and RESET in a generic switch/case function or a generic reducer, so I would only have to test those cases once and not in every reducer. There would be more generic cases in the future, that's why I want to avoid repetition.

This is the expected result :

const genericReducer = (state = initialState, action) => {
  switch (action.type) {
    case INITIALIZE:
      return {
        byId : _.keyBy(state.dogs, 'id'),
        ids: state.map(({id}) => id)
      }
    case RESET:
      return initialState
    default:
      return state
   }
}

const dogsReducer = ({ dogs: state = initialState, ...restOfState }, action) => {
  switch (action.type) {
    case SPECIFIC_DOG_ACTION:
      ...
    default:
      return state
  }
}

const catsReducer = ({ cats: state = initialState, ...restOfState}, action) => {
  switch (action.type) {
    case SPECIFIC_CAT_ACTION:
      ...
    default:
      return state
  }
}

const finalCatsReducer = mergeReducers(catsReducer, genericReducer)
const finalDogsReducer = mergeReducers(dogsReducer, genericReducer)

I already came up with a simple solution here :

const dogsReducer = ({ dogs: state = initialState, ...restOfState }, action) => {
  switch (action.type) {
    case SPECIFIC_DOG_ACTION:
      ...
    default:
      return genericReducer(state, action)
  }
}

const catsReducer = ({ cats: state = initialState, ...restOfState}, action) => {
  switch (action.type) {
    case SPECIFIC_CAT_ACTION:
      ...
    default:
      return genericReducer(state, action)
  }
}

but I'm not satisfied with it, as I would prefer to use a function to "inject" the reducer (mergeReducers(catsReducer, genericReducer)).

  • even if you don't think so, combineReducers is exactly what you are looking for. The state of the single reducers does not matter and you can also react to the same event in multiple reducers. redux.js.org/api/combinereducers – messerbill Aug 13 at 14:30
  • @messerbill how would that work since both reducers work with the same part of the state there ? – obscure18 Aug 13 at 14:44
  • ah sorry now i got it. Why don't you simply write a function (containing the redudant code) and call that function inside every reducer which needs it? In this case you could use the same logic in multiple reducers but keep every state clean. If you need to access the state of one reducer inside of another one it seems to be kind of an anti pattern imho – messerbill Aug 13 at 14:50
  • @messerbill Isn't that what I already tried? And I know it is not how people generally use Redux, as they use selectors with smart actions rather than use reducers which are kept as thin as possible. That's not the point of the question. – obscure18 Aug 13 at 14:58
  • 1
    Thank you for your help, however it's not exactly what I have been looking for. By writing to you, I searched on google with different keywords and I found some useful links like this one : github.com/markerikson/redux-ecosystem-links/blob/master/… which suggests a tool for reducers chaining. That is exactly what I was searching for ! – obscure18 Aug 13 at 15:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.