redux-vertical
Version:
Build redux vertically
58 lines (47 loc) • 1.46 kB
text/typescript
import type {
Action,
Reducer,
ReducersMapObject,
StateFromReducersMapObject,
} from 'redux';
import invariant from 'invariant';
import isPlainObject from './utils/isPlainObject';
export default function combineReducers(handlers: ReducersMapObject): Reducer {
invariant(
isPlainObject(handlers),
'combineReducers expected a dictionary object of reducers but found %s',
handlers,
);
// check the reducers
Object.keys(handlers).forEach((ns) => {
const reducer = handlers[ns];
invariant(
typeof reducer === 'function',
'reducer for %s should be functions but found %s',
ns,
reducer,
);
});
// create final reducer
function finalReducer(
state: StateFromReducersMapObject<typeof handlers> = {},
action: Action,
): StateFromReducersMapObject<typeof handlers> {
let hasChanged = false;
const nextState: StateFromReducersMapObject<typeof handlers> = {};
Object.keys(handlers).forEach((ns) => {
const reducer = handlers[ns];
const previousStateForKey = state[ns];
const nextStateForKey = reducer(previousStateForKey, action);
invariant(
!(typeof nextStateForKey === 'undefined'),
'expected defined state for ns %s',
ns,
);
nextState[ns] = nextStateForKey;
hasChanged = hasChanged || nextStateForKey !== previousStateForKey;
});
return hasChanged ? nextState : state;
}
return finalReducer;
}