Composing higher order reducers in Redux

2019-07-07 09:18发布

问题:

I've created some factory functions that give me simple (or more advanced) reducers. For example (simple one - base on action type set RequestState constant as a value):

export const reduceRequestState = (requestTypes: RequestActionTypes) =>
    (state: RequestState = RequestState.None, action: Action): RequestState => {
        switch (action.type) {
            case requestTypes.start:
                return RequestState.Waiting;
            case requestTypes.success:
                return RequestState.Success;
            case requestTypes.error:
                return RequestState.Error;
            case requestTypes.reset:
                return RequestState.None;
            default:
                return state;
        }
    };

Using those factory functions and combineReducers from redux I can compose them into fully functional reducer that handles most of my casual actions. That gives me readable code and prevents me from making silly mistakes.

Factories are good for common actions but when I need to add some custom behavior (for action type) which should modify some part of the store significantly I would like to write a custom part of the reducer that will handle that action for me. The idea is to compose reducers in an iterate manner, so combineReducers but for an array. This way I could use my factories creating reducer and then combine it with my custom reducer that handles some specific actions. The combineReducers for an array would then call the first one, recognize that nothing has changed and call the second (custom) one to handle the action.

I was looking for some solution and found redux-actions but do not quite like the way it links actions and reducers making the semantics little different from what I'm used to. Maybe I do not get it, but eventually I like to see that my reducer is written as pure function.

I am looking for some hint that will show me the way. Is there any library or project that uses any kind of higher order reducers and combines them in some way? Are there any downsides regarding composing reducers like described above?

回答1:

Yep, since reducers are just functions, there's an infinite number of ways you can organize the logic, and composing multiple functions together is very encouraged.

The "reducers in an array" idea you're looking for is https://github.com/acdlite/reduce-reducers. I use it frequently in my own app for exactly that kind of behavior - running a combineReducers-generated reducer first, then running reducers for more specific behavior in turn.

I've written a section for the Redux docs called Structuring Reducers, which covers a number of topics related to reducer logic. That includes useful patterns beyond the usual combineReducers approach.

I also have a list of many other reducer-related utilities as part of my Redux addons catalog.