diff --git a/packages/react-instantsearch/examples/react-router/src/App.js b/packages/react-instantsearch/examples/react-router/src/App.js index e896f4a083..9204eaf243 100644 --- a/packages/react-instantsearch/examples/react-router/src/App.js +++ b/packages/react-instantsearch/examples/react-router/src/App.js @@ -7,6 +7,7 @@ import { import {withRouter} from 'react-router'; import 'react-instantsearch-theme-algolia/style.css'; import qs from 'qs'; +import {isEqual} from 'lodash'; class App extends Component { constructor(props) { @@ -18,6 +19,10 @@ class App extends Component { this.setState({searchState: qs.parse(this.props.router.location.query)}); } + shouldComponentUpdate(nextProps, nextState) { + return !isEqual(this.state.searchState, nextState.searchState); + } + onSearchStateChange(nextSearchState) { const THRESHOLD = 700; const newPush = Date.now(); diff --git a/packages/react-instantsearch/src/core/createConnector.js b/packages/react-instantsearch/src/core/createConnector.js index 0ed7bb06e7..07a37fbdbf 100644 --- a/packages/react-instantsearch/src/core/createConnector.js +++ b/packages/react-instantsearch/src/core/createConnector.js @@ -1,5 +1,5 @@ import React, {PropTypes, Component} from 'react'; -import {has} from 'lodash'; +import {has, isEqual} from 'lodash'; import {shallowEqual, getDisplayName} from './utils'; @@ -97,7 +97,7 @@ export default function createConnector(connectorDesc) { } componentWillReceiveProps(nextProps) { - if (!shallowEqual(this.props, nextProps)) { + if (!isEqual(this.props, nextProps)) { this.setState({ props: this.getProvidedProps(nextProps), }); diff --git a/packages/react-instantsearch/src/core/createConnector.test.js b/packages/react-instantsearch/src/core/createConnector.test.js index 44b8e35af1..c69ecafd9d 100644 --- a/packages/react-instantsearch/src/core/createConnector.test.js +++ b/packages/react-instantsearch/src/core/createConnector.test.js @@ -31,14 +31,16 @@ describe('createConnector', () => { const props = { hello: 'there', }; - const wrapper = mount(, {context: { - ais: { - store: { - getState: () => state, - subscribe: () => null, + const wrapper = mount(, { + context: { + ais: { + store: { + getState: () => state, + subscribe: () => null, + }, }, }, - }}); + }); const args = getProvidedProps.mock.calls[0]; expect(args[0]).toEqual(props); expect(args[1]).toBe(state.widgets); @@ -59,14 +61,16 @@ describe('createConnector', () => { })(Dummy); const state = createState(); let props = {hello: 'there'}; - const wrapper = mount(, {context: { - ais: { - store: { - getState: () => state, - subscribe: () => null, + const wrapper = mount(, { + context: { + ais: { + store: { + getState: () => state, + subscribe: () => null, + }, }, }, - }}); + }); props = {hello: 'you'}; wrapper.setProps(props); expect(getProvidedProps.mock.calls.length).toBe(2); @@ -98,16 +102,18 @@ describe('createConnector', () => { hello: 'there', }; let listener; - const wrapper = mount(, {context: { - ais: { - store: { - getState: () => state, - subscribe: l => { - listener = l; + const wrapper = mount(, { + context: { + ais: { + store: { + getState: () => state, + subscribe: l => { + listener = l; + }, }, }, }, - }}); + }); expect(wrapper.find(Dummy).props()).toEqual({...props, ...state.widgets}); state = { ...createState(), @@ -134,40 +140,53 @@ describe('createConnector', () => { getId, })(() => null); const unsubscribe = jest.fn(); - const wrapper = mount(, {context: { - ais: { - store: { - getState: () => ({}), - subscribe: () => unsubscribe, + const wrapper = mount(, { + context: { + ais: { + store: { + getState: () => ({}), + subscribe: () => unsubscribe, + }, }, }, - }}); + }); expect(unsubscribe.mock.calls.length).toBe(0); wrapper.unmount(); expect(unsubscribe.mock.calls.length).toBe(1); }); it('doesn\'t update the component when passed props don\'t change', () => { - const getProvidedProps = jest.fn(() => {}); + const getProvidedProps = jest.fn(() => { + }); + const getSearchParameters = jest.fn(() => { + }); + const update = jest.fn(); const Dummy = jest.fn(() => null); const Connected = createConnector({ displayName: 'CoolConnector', getProvidedProps, + getSearchParameters, getId, })(Dummy); - const wrapper = mount(, {context: { - ais: { - store: { - getState: () => ({}), - subscribe: () => null, + const wrapper = mount(, { + context: { + ais: { + store: { + getState: () => ({}), + subscribe: () => null, + }, + widgetsManager: { + registerWidget: () => null, + update, + }, }, }, - }}); - expect(Dummy.mock.calls.length).toBe(1); - wrapper.setProps({hello: 'there'}); - expect(Dummy.mock.calls.length).toBe(2); - wrapper.setProps({hello: 'there'}); - expect(Dummy.mock.calls.length).toBe(2); + }); + expect(update.mock.calls.length).toBe(0); + wrapper.setProps({hello: 'there', another: ['one', 'two']}); + expect(update.mock.calls.length).toBe(1); + wrapper.setProps({hello: 'there', another: ['one', 'two']}); + expect(update.mock.calls.length).toBe(1); }); });