0

I joined a project which is written in React.js with redux and saga. Reducers in the store are written with the use of pipe function:

export const HighestOrderReducer = (...higherOrderReducers) => (baseReducer) =>
  higherOrderReducers.reduce(
    (reducer, nextHigherOrderReducer) => nextHigherOrderReducer(reducer),
    baseReducer
  );

so, I have, for example a dispatch of an action:

 dispatch(createSocketConnection(token));

that creates an action with type SOCKET_ACTION_TYPES.GET.START and payload token.

this is how the reducer for this slice looks like:

export default HighestOrderReducer (
  withResetState(SOCKET_ACTION_TYPES.RESET_STATE, initialState),
  withLoadable({
    isLoadingActionType: [SOCKET_ACTION_TYPES.GET.START],
    successActionType: [SOCKET_ACTION_TYPES.GET.SUCCESS],
    errorActionType: [SOCKET_ACTION_TYPES.GET.ERROR]
  })
)(reducer);

which is a pipe function, and can be re-written as

  withLoadable({
    isLoadingActionType: [SOCKET_ACTION_TYPES.GET.START],
    successActionType: [SOCKET_ACTION_TYPES.GET.SUCCESS],
    errorActionType: [SOCKET_ACTION_TYPES.GET.ERROR]
  })
(withResetState(resetStateActionType, initialState)(reducer)(state, action))
(state, action)

Here are the withResetState, withLoadable and reducer functions:

// the first function of the pipeline
export const withResetState = (resetStateActionType, initialState) => (baseReducer) => (state, action) => {
  const newState = action.type === resetStateActionType ? { ...initialState } : state;
  return baseReducer(newState, action);
};

now, if you look at the withResetState function, with the given action type and reducer it is returning an object, initialState. My problem is that in order for the second function of the pipe, withLoadable, to work, the first one is supposed to return some sort of a function, which, it doesn't to the best of my knowledge.

So, could you please let me know weather I missed something and the first function does return a function or I found a bug in the existing project?

Eli
  • 41
  • 7

1 Answers1

1

I think you've misread the code. withResetState does return a function, because it's written using nested arrow functions:

const withResetState = (resetStateActionType, initialState) => (baseReducer) => (state, action) => {
  const newState = action.type === resetStateActionType ? { ...initialState } : state;
  return baseReducer(newState, action);
};

This can be rewritten as:

function withResetState(resetStateActionType, initialState) {
  return function wrapBaseReducer(baseReducer) {
    return function actualReducer(state, action) {
      const newState = action.type === resetStateActionType ? { ...initialState } : state;
      return baseReducer(newState, action);
    }

  }
}

That actualReducer is the final reducer function being used.

That said, while Redux itself does emphasize use of Functional Programming principles, and we even show use of higher-order reducers in our docs...

personally I find this to be over-abstracted and very hard to follow, and would have recommended against writing the code this way in the first place.

markerikson
  • 63,178
  • 10
  • 141
  • 157