Skip to content

Instantly share code, notes, and snippets.

@vmasto
Created March 13, 2017 00:53
Show Gist options
  • Select an option

  • Save vmasto/c434c23929035cbe23e99dc14fee4147 to your computer and use it in GitHub Desktop.

Select an option

Save vmasto/c434c23929035cbe23e99dc14fee4147 to your computer and use it in GitHub Desktop.
Reducer Extensions
/**
* A higher order function that takes a reducer and an extension
* and returns a reducer amplified with provided extensions on
* existing or new action types.
*
* Extensions are objects containing the action `type` attribute
* and an `actionTypeExtension` function which takes `state` and
* the `action` and must return an object to append to the reducer's
* new state.
*
* Example of an extension:
* {
* type: ACTION_SUCCESS,
* actionTypeExtension: (state, action) => ({
* foo: action.payload.foo
* })
* }
*
* @param {Function} reducer - The reducer to extend
* @param {Array<Object>} extensions - An array of extensions actions
* with which to amplify the reducer
*
* @returns {Function} - The extended reducer
*/
const extendedReducer = (reducer, extensions) => (state, action) => {
if (!extensions || !action) {
return reducer(state, action);
}
const { type } = action;
const extension = extensions.find(x => x.type === type);
if (extension && extension.type === type) {
if (typeof extension.actionTypeExtension !== 'function') {
throw new Error('Expecting extension to contain an `actionTypeExtension` method.');
}
return {
...reducer(state, action),
...extension.actionTypeExtension(state, action),
};
}
return reducer(state, action);
};
export default extendedReducer;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment