diff --git a/src/components/connectAdvanced.js b/src/components/connectAdvanced.js index 6169fcb9a..0678a8007 100644 --- a/src/components/connectAdvanced.js +++ b/src/components/connectAdvanced.js @@ -291,7 +291,7 @@ export default function connectAdvanced( }) // Our re-subscribe logic only runs when the store/subscription setup changes - useEffect(() => { + useIsomorphicLayoutEffect(() => { // If we're not subscribed to the store, nothing to do here if (!shouldHandleStateChanges) return diff --git a/test/components/connect.spec.js b/test/components/connect.spec.js index 9e8a3a9c6..b2bbe2a4d 100644 --- a/test/components/connect.spec.js +++ b/test/components/connect.spec.js @@ -1926,6 +1926,38 @@ describe('React', () => { expect(mapStateToProps).toHaveBeenCalledTimes(2) }) + + it('should not notify nested components after they are unmounted', () => { + @connect(state => ({ count: state })) + class Parent extends Component { + render() { + return this.props.count === 1 ? : null + } + } + + const mapStateToProps = jest.fn(state => ({ count: state })) + @connect(mapStateToProps) + class Child extends Component { + render() { + return
{this.props.count}
+ } + } + + const store = createStore((state = 0, action) => + action.type === 'INC' ? state + 1 : state + ) + rtl.render( + + + + ) + + expect(mapStateToProps).toHaveBeenCalledTimes(0) + store.dispatch({ type: 'INC' }) + expect(mapStateToProps).toHaveBeenCalledTimes(1) + store.dispatch({ type: 'INC' }) + expect(mapStateToProps).toHaveBeenCalledTimes(1) + }) }) describe('Custom context and store-as-prop', () => {