diff --git a/README.md b/README.md index 897cda7..6eaac7a 100644 --- a/README.md +++ b/README.md @@ -15,14 +15,12 @@ the API is straightforward: ```JS $ngRedux.connect(selector, callback, disableCaching = false); -//OR -$ngRedux.connect([selector1, selector2, ...], callback, disableCaching = false); ``` -Where '''selector''' is a function taking for single argument the entire redux Store's state (a plain JS object) and returns another object, which is the slice of the state that your component is interested in. +Where `selector` is a function that takes Redux's entire store state as argument and returns an object that contains the slices of store state that your component is interested in. e.g: ```JS -state => state.todos +state => ({todos: state.todos}) ``` Note: if you are not familiar with this syntax, go and check out the [MDN Guide on fat arrow functions (ES2015)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) @@ -77,7 +75,7 @@ class TodoLoaderController { constructor($ngRedux) { this.todos = []; - $ngRedux.connect(state => state.todos, todos => this.todos = todos); + $ngRedux.connect(state => ({todos: state.todos}), ({todos}) => this.todos = todos); } [...] @@ -94,11 +92,11 @@ You can also grab multiple slices of the state by passing an array of selectors: constructor(reduxConnector) { this.todos = []; this.users = []; - $ngRedux.connect([ - state => state.todos, - state => state.users - ], - (todos, users) => { + $ngRedux.connect(state => ({ + todos: state.todos, + users: state.users + }), + ({todos, users}) => { this.todos = todos this.users = users; }); @@ -114,7 +112,7 @@ You can close a connection like this: constructor(reduxConnector) { this.todos = []; - this.unsubscribe = reduxConnector.connect(state => state.todos, todos => this.todos = todos); + this.unsubscribe = reduxConnector.connect(state => ({todos: state.todos}), ({todos}) => this.todos = todos); } destroy() { @@ -137,7 +135,7 @@ Each time Redux's Store update, ng-redux will check if the slices specified via You can disable this behaviour, and force the callback to be executed even if the slices didn't change by setting ```disableCaching``` to true: ```JS -reduxConnector.connect(state => state.todos, todos => this.todos = todos, true); +reduxConnector.connect(state => ({todos: state.todos}), ({todos}) => this.todos = todos, true); ``` diff --git a/src/components/connector.js b/src/components/connector.js index 311003b..9b3ada4 100644 --- a/src/components/connector.js +++ b/src/components/connector.js @@ -4,11 +4,7 @@ import invariant from 'invariant'; export default function Connector(store) { return { - connect: (selectors, callback, disableCaching = false) => { - if (!Array.isArray(selectors)) { - selectors = [selectors]; - } - + connect: (selector, callback, disableCaching = false) => { invariant( isFunction(callback), 'The callback parameter passed to connect must be a Function. Instead received %s.', @@ -16,13 +12,13 @@ export default function Connector(store) { ); //Initial update - let params = selectors.map(selector => selector(store.getState())); - callback(...params); + let params = selector(store.getState()); + callback(params); let unsubscribe = store.subscribe(() => { - let nextParams = selectors.map(selector => selector(store.getState())); + let nextParams = selector(store.getState()); if (disableCaching || !shallowEqual(params, nextParams)) { - callback(...nextParams); + callback(nextParams); params = nextParams; } }); diff --git a/test/components/connector.spec.js b/test/components/connector.spec.js index a388db2..64d28ef 100644 --- a/test/components/connector.spec.js +++ b/test/components/connector.spec.js @@ -1,6 +1,6 @@ import expect from 'expect'; import {createStore} from 'redux'; -import {default as Connector, copyArray} from '../../src/components/connector'; +import Connector from '../../src/components/connector'; describe('Connector', () => { let store; @@ -25,7 +25,7 @@ describe('Connector', () => { expect(counter).toBe(1); }); - it('Should call the function passed to connect when the store updates', () => { + it('Should call the callback passed to connect when the store updates', () => { let counter = 0; let callback = () => counter++; connector.connect(state => state, callback); @@ -34,18 +34,10 @@ describe('Connector', () => { expect(counter).toBe(3); }); - it('Should accept a function or an array of function as selector', () => { - let receivedState1, receivedState2; - connector.connect(state => state.foo, newState => receivedState1 = newState); - connector.connect([state => state.foo], newState => receivedState2 = newState); - expect(receivedState1).toBe('bar'); - expect(receivedState1).toBe(receivedState2); - }) - it('Should prevent unnecessary updates when state does not change (shallowly)', () => { let counter = 0; let callback = () => counter++; - connector.connect(state => state.baz, callback); + connector.connect(state => ({baz: state.baz}), callback); store.dispatch({type: 'ACTION', payload: 0}); store.dispatch({type: 'ACTION', payload: 0}); store.dispatch({type: 'ACTION', payload: 1}); @@ -55,7 +47,7 @@ describe('Connector', () => { it('Should disable caching when disableCaching is set to true', () => { let counter = 0; let callback = () => counter++; - connector.connect(state => state.baz, callback, true); + connector.connect(state => ({baz: state.baz}), callback, true); store.dispatch({type: 'ACTION', payload: 0}); store.dispatch({type: 'ACTION', payload: 0}); store.dispatch({type: 'ACTION', payload: 1}); @@ -64,18 +56,20 @@ describe('Connector', () => { it('Should pass the selected state as argument to the callback', () => { let receivedState; - connector.connect(state => state.foo, newState => receivedState = newState); - store.dispatch({type: 'ACTION', payload: 1}); - expect(receivedState).toBe('bar'); + connector.connect(state => ({ + myFoo: state.foo + }), newState => receivedState = newState); + expect(receivedState).toEqual({myFoo: 'bar'}); }); - it('Should pass all the selected state as argument to the callback when provided an array of selectors', () => { - connector.connect([state => state.foo, state => state.anotherState], - (foo, anotherState) => { + it('Should allow multiple store slices to be selected', () => { + connector.connect(state => ({ + foo: state.foo, + anotherState: state.anotherState + }), ({foo, anotherState}) => { expect(foo).toBe('bar'); expect(anotherState).toBe(12); - }); - store.dispatch({type: 'ACTION', payload: 1}); + }); }); it('Should return an unsubscribing function', () => {