UNPKG

redux

Version:

Predictable state container for JavaScript apps

114 lines (87 loc) 4.78 kB
'use strict'; exports.__esModule = true; exports['default'] = combineReducers; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } var _createStore = require('../createStore'); var _utilsIsPlainObject = require('../utils/isPlainObject'); var _utilsIsPlainObject2 = _interopRequireDefault(_utilsIsPlainObject); var _utilsMapValues = require('../utils/mapValues'); var _utilsMapValues2 = _interopRequireDefault(_utilsMapValues); var _utilsPick = require('../utils/pick'); var _utilsPick2 = _interopRequireDefault(_utilsPick); /* eslint-disable no-console */ function getErrorMessage(key, action) { var actionType = action && action.type; var actionName = actionType && '"' + actionType.toString() + '"' || 'an action'; return 'Reducer "' + key + '" returned undefined handling ' + actionName + '. ' + 'To ignore an action, you must explicitly return the previous state.'; } function verifyStateShape(initialState, currentState) { var reducerKeys = Object.keys(currentState); if (reducerKeys.length === 0) { console.error('Store does not have a valid reducer. Make sure the argument passed ' + 'to combineReducers is an object whose values are reducers.'); return; } if (!_utilsIsPlainObject2['default'](initialState)) { console.error('initialState has unexpected type of "' + ({}).toString.call(initialState).match(/\s([a-z|A-Z]+)/)[1] + '". Expected initialState to be an object with the following ' + ('keys: "' + reducerKeys.join('", "') + '"')); return; } var unexpectedKeys = Object.keys(initialState).filter(function (key) { return reducerKeys.indexOf(key) < 0; }); if (unexpectedKeys.length > 0) { console.error('Unexpected ' + (unexpectedKeys.length > 1 ? 'keys' : 'key') + ' ' + ('"' + unexpectedKeys.join('", "') + '" in initialState will be ignored. ') + ('Expected to find one of the known reducer keys instead: "' + reducerKeys.join('", "') + '"')); } } /** * Turns an object whose values are different reducer functions, into a single * reducer function. It will call every child reducer, and gather their results * into a single state object, whose keys correspond to the keys of the passed * reducer functions. * * @param {Object} reducers An object whose values correspond to different * reducer functions that need to be combined into one. One handy way to obtain * it is to use ES6 `import * as reducers` syntax. The reducers may never return * undefined for any action. Instead, they should return their initial state * if the state passed to them was undefined, and the current state for any * unrecognized action. * * @returns {Function} A reducer function that invokes every reducer inside the * passed object, and builds a state object with the same shape. */ function combineReducers(reducers) { var finalReducers = _utilsPick2['default'](reducers, function (val) { return typeof val === 'function'; }); Object.keys(finalReducers).forEach(function (key) { var reducer = finalReducers[key]; if (typeof reducer(undefined, { type: _createStore.ActionTypes.INIT }) === 'undefined') { throw new Error('Reducer "' + key + '" returned undefined during initialization. ' + 'If the state passed to the reducer is undefined, you must ' + 'explicitly return the initial state. The initial state may ' + 'not be undefined.'); } var type = Math.random().toString(36).substring(7).split('').join('.'); if (typeof reducer(undefined, { type: type }) === 'undefined') { throw new Error('Reducer "' + key + '" returned undefined when probed with a random type. ' + ('Don\'t try to handle ' + _createStore.ActionTypes.INIT + ' or other actions in "redux/*" ') + 'namespace. They are considered private. Instead, you must return the ' + 'current state for any unknown actions, unless it is undefined, ' + 'in which case you must return the initial state, regardless of the ' + 'action type. The initial state may not be undefined.'); } }); var defaultState = _utilsMapValues2['default'](finalReducers, function () { return undefined; }); var stateShapeVerified; return function combination(state, action) { if (state === undefined) state = defaultState; var finalState = _utilsMapValues2['default'](finalReducers, function (reducer, key) { var newState = reducer(state[key], action); if (typeof newState === 'undefined') { throw new Error(getErrorMessage(key, action)); } return newState; }); if (process.env.NODE_ENV !== 'production') { if (!stateShapeVerified) { verifyStateShape(state, finalState); stateShapeVerified = true; } } return finalState; }; } module.exports = exports['default'];