diff --git a/src/components/connectAdvanced.js b/src/components/connectAdvanced.js index fee9776df..066776e6d 100644 --- a/src/components/connectAdvanced.js +++ b/src/components/connectAdvanced.js @@ -203,11 +203,7 @@ export default function connectAdvanced( store ) - if (pure) { - return this.selectChildElement(derivedProps, forwardedRef) - } - - return + return this.selectChildElement(derivedProps, forwardedRef) } render() { diff --git a/test/components/connectAdvanced.spec.js b/test/components/connectAdvanced.spec.js new file mode 100644 index 000000000..6a47c8579 --- /dev/null +++ b/test/components/connectAdvanced.spec.js @@ -0,0 +1,183 @@ +import React, { Component } from 'react' +import * as rtl from 'react-testing-library' +import { Provider as ProviderMock, connectAdvanced } from '../../src/index.js' +import { createStore } from 'redux' +import 'jest-dom/extend-expect' + +describe('React', () => { + describe('connectAdvanced', () => { + it('should map state and render once on mount', () => { + const initialState = { + foo: 'bar' + } + + let mapCount = 0 + let renderCount = 0 + + const store = createStore(() => initialState) + + function Inner(props) { + renderCount++ + return
{JSON.stringify(props)}
+ } + + const Container = connectAdvanced(() => { + return state => { + mapCount++ + return state + } + })(Inner) + + const tester = rtl.render( + + + + ) + + expect(tester.getByTestId('foo')).toHaveTextContent('bar') + + expect(mapCount).toEqual(1) + expect(renderCount).toEqual(1) + }) + + it('should render on reference change', () => { + let mapCount = 0 + let renderCount = 0 + + // force new reference on each dispatch + const store = createStore(() => ({ + foo: 'bar' + })) + + function Inner(props) { + renderCount++ + return
{JSON.stringify(props)}
+ } + + const Container = connectAdvanced(() => { + return state => { + mapCount++ + return state + } + })(Inner) + + rtl.render( + + + + ) + + store.dispatch({ type: 'NEW_REFERENCE' }) + + // Should have mapped the state on mount and on the dispatch + expect(mapCount).toEqual(2) + + // Should have rendered on mount and after the dispatch bacause the map + // state returned new reference + expect(renderCount).toEqual(2) + }) + + it('should not render when the returned reference does not change', () => { + const staticReference = { + foo: 'bar' + } + + let mapCount = 0 + let renderCount = 0 + + // force new reference on each dispatch + const store = createStore(() => ({ + foo: 'bar' + })) + + function Inner(props) { + renderCount++ + return
{JSON.stringify(props)}
+ } + + const Container = connectAdvanced(() => { + return () => { + mapCount++ + // but return static reference + return staticReference + } + })(Inner) + + const tester = rtl.render( + + + + ) + + store.dispatch({ type: 'NEW_REFERENCE' }) + + expect(tester.getByTestId('foo')).toHaveTextContent('bar') + + // The state should have been mapped twice: on mount and on the dispatch + expect(mapCount).toEqual(2) + + // But the render should have been called only on mount since the map state + // did not return a new reference + expect(renderCount).toEqual(1) + }) + + it('should map state on own props change but not render when the reference does not change', () => { + const staticReference = { + foo: 'bar' + } + + let mapCount = 0 + let renderCount = 0 + + const store = createStore(() => staticReference) + + function Inner(props) { + renderCount++ + return
{JSON.stringify(props)}
+ } + + const Container = connectAdvanced(() => { + return () => { + mapCount++ + // return the static reference + return staticReference + } + })(Inner) + + class OuterComponent extends Component { + constructor() { + super() + this.state = { foo: 'FOO' } + } + + setFoo(foo) { + this.setState({ foo }) + } + + render() { + return ( +
+ +
+ ) + } + } + + let outerComponent + rtl.render( + + (outerComponent = c)} /> + + ) + + outerComponent.setFoo('BAR') + + // map on mount and on prop change + expect(mapCount).toEqual(2) + + // render only on mount but skip on prop change because no new + // reference was returned + expect(renderCount).toEqual(1) + }) + }) +})