Search code examples
typescriptreduxngrxngrx-store

Merge two reducers in NGRX


I am using @[email protected] and I have a reducer that is created in a factory as it is the same for several entities in my project.

function createEntityReducer(initialState, actions) {
  const reducer = createReducer(
    initialState,
    on(actions.loadAll.success, (state, action) => {
      ...
    })
  ); 
  return reducer;
}

const generalReducer = createEntityReducer(initialState, actions);

But I would like to extend this basic reducer for specific actions of a certain entity.

const specificReducer = createReducer(
        initialState,
        on(actions.loadChildren.success, (state, action) => {
          ...
        })
      );

How can I merge the two reducers, without having to create nested features, like this?

const reducer = mergeReducers(generalReducer, specificReducer);

Solution

  • After checking how the @ngrx/store/createReducer function works, I compose the below that seems to work correctly.

    function mergeReducers<TState>(
      ...reducers: ActionReducer<TState, Action>[]
    ): ActionReducer<TState, Action> {
      const mergedReducers = (
        state: TState | undefined,
        action: Action
      ): TState => {
        if (reducers.length === 0) {
          throw new Error('At least one reducer was expected');
        }
        const newState = reducers.reduce((initialState, reducer) => {
          const intermediaryState = reducer(initialState, action);
          return intermediaryState;
        }, state);
    
        return newState as TState;
      };
      return mergedReducers;
    }