diff --git a/packages/react-instantsearch/src/core/InstantSearch.js b/packages/react-instantsearch/src/core/InstantSearch.js index a18e4bacc2..a50ec6a94c 100644 --- a/packages/react-instantsearch/src/core/InstantSearch.js +++ b/packages/react-instantsearch/src/core/InstantSearch.js @@ -100,7 +100,9 @@ class InstantSearch extends Component { } onWidgetsInternalStateUpdate(searchState) { - searchState = this.onSearchStateChange(searchState); + searchState = this.aisManager.transitionState(searchState); + + this.onSearchStateChange(searchState); if (!this.isControlled) { this.aisManager.onExternalStateUpdate(searchState); @@ -108,13 +110,9 @@ class InstantSearch extends Component { } onSearchStateChange(searchState) { - searchState = this.aisManager.transitionState(searchState); - if (this.props.onSearchStateChange) { this.props.onSearchStateChange(searchState); } - - return searchState; } onSearchForFacetValues(searchState) { diff --git a/packages/react-instantsearch/src/core/createConnector.js b/packages/react-instantsearch/src/core/createConnector.js index 8c06cd296a..c2ac65119c 100644 --- a/packages/react-instantsearch/src/core/createConnector.js +++ b/packages/react-instantsearch/src/core/createConnector.js @@ -106,7 +106,13 @@ export default function createConnector(connectorDesc) { // Since props might have changed, we need to re-run getSearchParameters // and getMetadata with the new props. this.context.ais.widgetsManager.update(); - this.context.ais.onSearchStateChange(this.context.ais.store.getState().widgets); + if (connectorDesc.transitionState) { + this.context.ais.onSearchStateChange(connectorDesc.transitionState( + nextProps, + this.context.ais.store.getState().widgets, + this.context.ais.store.getState().widgets, + )); + } } } } diff --git a/packages/react-instantsearch/src/core/createConnector.test.js b/packages/react-instantsearch/src/core/createConnector.test.js index 02f9795c81..418debe005 100644 --- a/packages/react-instantsearch/src/core/createConnector.test.js +++ b/packages/react-instantsearch/src/core/createConnector.test.js @@ -215,12 +215,14 @@ describe('createConnector', () => { const getSearchParameters = jest.fn(() => { }); const onSearchStateChange = jest.fn(); + const transitionState = jest.fn(); const update = jest.fn(); const Dummy = jest.fn(() => null); const Connected = createConnector({ displayName: 'CoolConnector', getProvidedProps, getSearchParameters, + transitionState, getId, })(Dummy); const wrapper = mount(, { @@ -240,11 +242,14 @@ describe('createConnector', () => { }); expect(onSearchStateChange.mock.calls.length).toBe(0); expect(update.mock.calls.length).toBe(0); + expect(transitionState.mock.calls.length).toBe(0); wrapper.setProps({hello: 'there', another: ['one', 'two']}); expect(onSearchStateChange.mock.calls.length).toBe(1); + expect(transitionState.mock.calls.length).toBe(1); expect(update.mock.calls.length).toBe(1); wrapper.setProps({hello: 'there', another: ['one', 'two']}); expect(onSearchStateChange.mock.calls.length).toBe(1); + expect(transitionState.mock.calls.length).toBe(1); expect(update.mock.calls.length).toBe(1); }); }); @@ -338,11 +343,13 @@ describe('createConnector', () => { }); it('calls update when props change', () => { + const transitionState = jest.fn(); const Connected = createConnector({ displayName: 'CoolConnector', getProvidedProps: () => null, getMetadata: () => null, getId, + transitionState, })(() => null); const update = jest.fn(); const onSearchStateChange = jest.fn(); @@ -362,17 +369,53 @@ describe('createConnector', () => { }}); expect(update.mock.calls.length).toBe(0); expect(onSearchStateChange.mock.calls.length).toBe(0); + expect(transitionState.mock.calls.length).toBe(0); wrapper.setProps({hello: 'you'}); expect(update.mock.calls.length).toBe(1); expect(onSearchStateChange.mock.calls.length).toBe(1); + expect(transitionState.mock.calls.length).toBe(1); + }); + + it('dont trigger onSearchStateChange when props change and the component has no transitionState function', () => { + const Connected = createConnector({ + displayName: 'CoolConnector', + getProvidedProps: () => null, + getMetadata: () => null, + getId, + })(() => null); + const update = jest.fn(); + const onSearchStateChange = jest.fn(); + const props = {hello: 'there'}; + const wrapper = mount(, { + context: { + ais: { + store: { + getState: () => ({}), + subscribe: () => null, + }, + widgetsManager: { + registerWidget: () => null, + update, + }, + onSearchStateChange, + }, + }, + }); + expect(update.mock.calls.length).toBe(0); + expect(onSearchStateChange.mock.calls.length).toBe(0); + wrapper.setProps({hello: 'you'}); + expect(update.mock.calls.length).toBe(1); + expect(onSearchStateChange.mock.calls.length).toBe(0); }); it('dont update when props dont change', () => { + const transitionState = jest.fn(); const Connected = createConnector({ displayName: 'CoolConnector', getProvidedProps: () => null, getMetadata: () => null, getId, + transitionState, })(() => null); const onSearchStateChange = jest.fn(); const update = jest.fn(); @@ -392,9 +435,11 @@ describe('createConnector', () => { }}); expect(onSearchStateChange.mock.calls.length).toBe(0); expect(update.mock.calls.length).toBe(0); + expect(transitionState.mock.calls.length).toBe(0); wrapper.setProps({hello: 'there'}); expect(onSearchStateChange.mock.calls.length).toBe(0); expect(update.mock.calls.length).toBe(0); + expect(transitionState.mock.calls.length).toBe(0); }); it('unregisters itself on unmount', () => {