How to manage redux state using reduceReducers.

Usually when someone creates a redux app, the root reducer gets configured within combineReducers utility.

Suppose we have a simple state, that with fieldsuser, location and also it should track failures related to fetch of user or location. Also location failures must be displayed as warnings, and user related as errors. Those errors should be displayed as stack:

We could add a field called errors to both user and location sub-states, and our state would look like:

Advantages:

  • Any domain of the application can handle error tracking separately.

Disadvantages:

  • Hard to select all errors in the app, and display those in the error stack. Hypothetic selectErrors function should be aware of all modules in the app, that might track errors.

Another potential approach would be in creating separate sub-state for errors:

Advantages:

  • Easy to select all active errors.

Disadvantages:

  • errors reducer should handle failure actions for all modules in the app.

The main issue of both approaches occurs due to assumption, that any reducer should manage only its own part of the state. This is paradigm, brought to us by combineReducers , which will delegate all top level state values to individual reducers. Hence there’s no way to modify anything outside of area of responsibility of certain reducer.

As an alternative, full state might be passed and returned by each individual reducer:

You might notice, that in rootReducer state is explicitly piped through each reducer. This means that userReducer will manage previous store state, then result of userReducer will be passed as state parameter to the locationReducer and so on. This actually means that if reducers would be stored in an array, there could be a universal function that would organize that pipeline. This function is called reduceReducers and it can be imported from `reduce-reducers` npm package. Reducer code can now be simplified:

Advantages:

  • You can easily select all errors, and manage them in the errorsReducer . However you can still add user / location related errors in appropriate reducers.

Disadvantages:

  • Every reducer is now aware of full state, it gets harder to perform update operations.

However reduceReducers is not a replacement of combineReducers , in fact you may try use them together. Let extract userErrorReducerfrom userReducer and locationErrorReducerfromlocationReducer , those will just manage errors related to their modules. Now we can reduce all errors related reducers, and combine them together with user and location reducers.

Now each module can track its own errors, however those errors are stored in one source of truth. To get more familiar with this approach play with example above on this codesandbox.

React / typescript entusiast

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store