Search code examples
redux-toolkit

Extending redux-toolkit slice


I've got an interesting topic for you this time around. I am a little stuck with this topic since I've tackled it a few month ago.

I am trying to extend a redux toolkit slice:

EX: I have a slice defined, but I would like to add some more reducers. Or to override some reducers.

This I've manage to do with this:

//Extend slice function
/**
 *  @remarks
 * 
 *  This method extends an already declared slice in oreder to attach custom actions to the reducer.
 * 
 *  @param slice The root slice you want to extend
 *  @param caseReducers The case reducers you want to add to the current ones. Current slice reducers won't be override.
 *  @param extraReducers Extra reducers to add to the slice. Don't use this for slices that contain extra reducers! They will be overridden!
 *  
 * 
 *  @returns slice: Slice
 *  The extended slice containing the current reducers concatenated with the new caseReducers and with the extraReducers 
 *
 */

export const extendSlice = ( slice: Slice, caseReducers?: ValidateSliceCaseReducers<any, SliceCaseReducers<any>>, extraReducers?: ( ( builder: ActionReducerMapBuilder<NoInfer<any>> ) => void ) ) => {
  return createSlice( {
    name: slice.name,
    initialState: slice.getInitialState(),
    reducers: { ...caseReducers, ...slice.caseReducers },
    extraReducers
  } );
};

I was wondering if I can do the same thing with the extraReducers like I did with the caseReducers to oveeride/extend them. Or is there a point to do. Are the extraReducers inside the caseReducers? Asking this since I have no access to the extraReducers inside the slice.


Solution

  • You could wrap them instead:

    function extendSlice(originalSlice, caseReducers, extraReducers) {
      const wrappingSlice = createSlice({
        name: slice.name,
        initialState: slice.getInitialState(),
        reducers: caseReducers,
        extraReducers
      } );
    
    
      const wrappedReducer = (state, action) => wrappingSlice.reducer(originalSlice.reducer(state, action), action);
      return {
        ...wrappingSlice,
        reducer: wrappedReducer ,
        caseReducers: {
          ...wrappingSlice.caseReducers,
          ...originalSlice.caseReducers
        }
      }
    }