From 0aef2a57d7638ac2f04dd79c269e259b8a3fb2da Mon Sep 17 00:00:00 2001 From: Warren R Bank Date: Sun, 28 Jan 2018 13:34:52 -0800 Subject: [PATCH 1/3] enhancement: store.subscribe(listener, filter) new (optional) input parameter: `filter` * its purpose is to conditionally filter when `listener` is called * when its value is: * undefined: * `listener` is called as normal * `function`: * input: (oldState, newState) * output: boolean * when truthy, `listener` is not informed of this state change * `boolean` && true: * `listener` is not informed when `newState` is equal (by reference) to `oldState` --- src/createStore.js | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/createStore.js b/src/createStore.js index d4a6ad9fd3..d0c29a605f 100644 --- a/src/createStore.js +++ b/src/createStore.js @@ -98,11 +98,17 @@ export default function createStore(reducer, preloadedState, enhancer) { * @param {Function} listener A callback to be invoked on every dispatch. * @returns {Function} A function to remove this change listener. */ - function subscribe(listener) { + function subscribe(listener, filter) { if (typeof listener !== 'function') { throw new Error('Expected the listener to be a function.') } + if (typeof filter !== 'function') { + filter = (filter === true) ? pure_filter : false + } + + const nextListener = {listener, filter} + if (isDispatching) { throw new Error( 'You may not call store.subscribe() while the reducer is executing. ' + @@ -115,7 +121,7 @@ export default function createStore(reducer, preloadedState, enhancer) { let isSubscribed = true ensureCanMutateNextListeners() - nextListeners.push(listener) + nextListeners.push(nextListener) return function unsubscribe() { if (!isSubscribed) { @@ -132,11 +138,15 @@ export default function createStore(reducer, preloadedState, enhancer) { isSubscribed = false ensureCanMutateNextListeners() - const index = nextListeners.indexOf(listener) + const index = nextListeners.indexOf(nextListener) nextListeners.splice(index, 1) } } + function pure_filter(oldState, newState) { + return oldState === newState + } + /** * Dispatches an action. It is the only way to trigger a state change. * @@ -181,6 +191,8 @@ export default function createStore(reducer, preloadedState, enhancer) { throw new Error('Reducers may not dispatch actions.') } + const oldState = currentState + try { isDispatching = true currentState = currentReducer(currentState, action) @@ -190,8 +202,11 @@ export default function createStore(reducer, preloadedState, enhancer) { const listeners = (currentListeners = nextListeners) for (let i = 0; i < listeners.length; i++) { - const listener = listeners[i] - listener() + const {listener, filter} = listeners[i] + const apply_filter = filter && filter(oldState, currentState) + if (! apply_filter) { + listener() + } } return action From 5d27ee079aaaa7321d579702c3fb525a42f53d79 Mon Sep 17 00:00:00 2001 From: Warren R Bank Date: Sun, 28 Jan 2018 13:59:47 -0800 Subject: [PATCH 2/3] lint --- src/createStore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/createStore.js b/src/createStore.js index d0c29a605f..3a2e27be73 100644 --- a/src/createStore.js +++ b/src/createStore.js @@ -104,7 +104,7 @@ export default function createStore(reducer, preloadedState, enhancer) { } if (typeof filter !== 'function') { - filter = (filter === true) ? pure_filter : false + filter = filter === true ? pure_filter : false } const nextListener = {listener, filter} From a2a7470ce09a028d184f6023739e02de97519a47 Mon Sep 17 00:00:00 2001 From: Warren R Bank Date: Sun, 28 Jan 2018 14:51:00 -0800 Subject: [PATCH 3/3] lint npm install node_modules/.bin/prettier "src/createStore.js" >"src/createStore.js" --- src/createStore.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/createStore.js b/src/createStore.js index 3a2e27be73..cf5738063d 100644 --- a/src/createStore.js +++ b/src/createStore.js @@ -107,7 +107,7 @@ export default function createStore(reducer, preloadedState, enhancer) { filter = filter === true ? pure_filter : false } - const nextListener = {listener, filter} + const nextListener = { listener, filter } if (isDispatching) { throw new Error( @@ -202,9 +202,9 @@ export default function createStore(reducer, preloadedState, enhancer) { const listeners = (currentListeners = nextListeners) for (let i = 0; i < listeners.length; i++) { - const {listener, filter} = listeners[i] + const { listener, filter } = listeners[i] const apply_filter = filter && filter(oldState, currentState) - if (! apply_filter) { + if (!apply_filter) { listener() } }