Skip to content

Instantly share code, notes, and snippets.

@gabemeola
Created October 25, 2018 20:09
Show Gist options
  • Save gabemeola/1641c75d82df434bf36035a10869676b to your computer and use it in GitHub Desktop.
Save gabemeola/1641c75d82df434bf36035a10869676b to your computer and use it in GitHub Desktop.
Combines Redux reducers with a top level root reducer
/**
* Combines reducers with root reducer
*
* @param {function(Object, Object): Object} rootReducer
* @param {Object<string, function(Object, Object): Object>} [reducers={}]
* @returns {function(Object, Object): Object}
*/
export default function combineReducersWithRoot(rootReducer, reducers = {}) {
const entries = Object.entries(reducers);
return (state, action) => {
const rootState = rootReducer(state, action);
// Merge in reducers
return entries.reduce((accumulator, [key, fn]) => {
// Check if nested state is undefined
const reducerState = typeof state !== 'undefined'
? state[key]
: state;
accumulator[key] = fn(reducerState, action);
return accumulator;
}, {
// Root State is the initial reduce value
...rootState,
});
};
}
import combineReducersWithRoot from './combineReducersWithRoot';
const initState = { name: 'paypal' }
const root = (state = initState, action) => {
if (action.type === 'test') {
return {
...state,
name: action.name,
}
}
return state;
}
it('should merge root reducer', () => {
const reducer = combineReducersWithRoot(root);
expect(reducer).toBeInstanceOf(Function)
expect(reducer(undefined, {})).toEqual(initState)
expect(reducer({ ...initState }, { type: 'test', name: 'facebook' })).toEqual({ name: 'facebook' })
})
it('should merge nested reducers', () => {
const initStats = { people: 1000 }
const statsReducer = (state = initStats, action) => {
if (action.type === 'ADD_PEOPLE') {
return {
...state,
people: state.people + action.add,
}
}
return state;
}
const reducer = combineReducersWithRoot(root, {
stats: statsReducer,
})
expect(reducer).toBeInstanceOf(Function);
expect(reducer(undefined, {})).toEqual({ ...initState, stats: initStats })
expect(reducer({ ...initState, stats: initStats }, { type: 'ADD_PEOPLE', add: 5 })).toEqual({
...initState,
stats: {
...initStats,
people: initStats.people + 5
}
})
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment