From 3824a21d0cd0af4a60f4077c963120e17ff2c5b4 Mon Sep 17 00:00:00 2001 From: Robert Plummer Date: Thu, 16 Jun 2016 14:28:04 -0400 Subject: [PATCH 1/2] Addresses #959 without affecting the library's existing functionality. Ultimately tries to prevent re-renders when multiple states are needed in quick succession. --- src/createStore.js | 62 +++++++++++++++++++++++----------------- test/createStore.spec.js | 14 +++++++++ 2 files changed, 50 insertions(+), 26 deletions(-) diff --git a/src/createStore.js b/src/createStore.js index 9f4ab038fe..039f1d81eb 100644 --- a/src/createStore.js +++ b/src/createStore.js @@ -122,7 +122,7 @@ export default function createStore(reducer, preloadedState, enhancer) { } /** - * Dispatches an action. It is the only way to trigger a state change. + * Dispatches action(s). It is the only way to trigger a state change. * * The `reducer` function, used to create the store, will be called with the * current state tree and the given `action`. Its return value will @@ -139,45 +139,55 @@ export default function createStore(reducer, preloadedState, enhancer) { * a good idea to keep actions serializable so you can record and replay user * sessions, or use the time travelling `redux-devtools`. An action must have * a `type` property which may not be `undefined`. It is a good idea to use - * string constants for action types. + * string constants for action types. Can handle multiple dispatches so to + * keep re-renders at a minimum. * - * @returns {Object} For convenience, the same action object you dispatched. + * @returns {Object|Array} For convenience, the same action object you dispatched. + * If multiple actions are supplied, then will be returned as an Array. * * Note that, if you use a custom middleware, it may wrap `dispatch()` to * return something else (for example, a Promise you can await). */ - function dispatch(action) { - if (!isPlainObject(action)) { - throw new Error( - 'Actions must be plain objects. ' + - 'Use custom middleware for async actions.' - ) - } + function dispatch() { + var actions = [] + var i; + for (i = 0; i < arguments.length; i++) { + var action = arguments[i] - if (typeof action.type === 'undefined') { - throw new Error( - 'Actions may not have an undefined "type" property. ' + - 'Have you misspelled a constant?' - ) - } + if (!isPlainObject(action)) { + throw new Error( + 'Actions must be plain objects. ' + + 'Use custom middleware for async actions.' + ) + } - if (isDispatching) { - throw new Error('Reducers may not dispatch actions.') - } + if (typeof action.type === 'undefined') { + throw new Error( + 'Actions may not have an undefined "type" property. ' + + 'Have you misspelled a constant?' + ) + } + + if (isDispatching) { + throw new Error('Reducers may not dispatch actions.') + } + + try { + isDispatching = true + currentState = currentReducer(currentState, action) + } finally { + isDispatching = false + } - try { - isDispatching = true - currentState = currentReducer(currentState, action) - } finally { - isDispatching = false + actions.push(action) } var listeners = currentListeners = nextListeners - for (var i = 0; i < listeners.length; i++) { + for (i = 0; i < listeners.length; i++) { listeners[i]() } - return action + return actions.length > 1 ? actions : actions[0] } /** diff --git a/test/createStore.spec.js b/test/createStore.spec.js index 369bb98af3..80c1322f1b 100644 --- a/test/createStore.spec.js +++ b/test/createStore.spec.js @@ -77,6 +77,20 @@ describe('createStore', () => { ]) }) + it('can handle multiple dispatches', () => { + const store = createStore(reducers.todos) + store.dispatch(addTodo('Hello'), addTodo('World')) + expect(store.getState()).toEqual([ + { + id: 1, + text: 'Hello' + }, { + id: 2, + text: 'World' + } + ]) + }) + it('applies the reducer to the initial state', () => { const store = createStore(reducers.todos, [ { From b420090de77a19b711651cf161a533ae2ffa26f1 Mon Sep 17 00:00:00 2001 From: Robert Plummer Date: Thu, 16 Jun 2016 14:43:41 -0400 Subject: [PATCH 2/2] lint --- src/createStore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/createStore.js b/src/createStore.js index 039f1d81eb..09af082d8b 100644 --- a/src/createStore.js +++ b/src/createStore.js @@ -150,7 +150,7 @@ export default function createStore(reducer, preloadedState, enhancer) { */ function dispatch() { var actions = [] - var i; + var i for (i = 0; i < arguments.length; i++) { var action = arguments[i]