diff --git a/src/hooks/useSelector.js b/src/hooks/useSelector.js index d6e85928a..52cf28dba 100644 --- a/src/hooks/useSelector.js +++ b/src/hooks/useSelector.js @@ -42,11 +42,9 @@ function useSelectorWithStoreAndSubscription( throw err } - useIsomorphicLayoutEffect(() => { - latestSelector.current = selector - latestSelectedState.current = selectedState - latestSubscriptionCallbackError.current = undefined - }) + latestSelector.current = selector + latestSelectedState.current = selectedState + latestSubscriptionCallbackError.current = undefined useIsomorphicLayoutEffect(() => { function checkForUpdates() { diff --git a/test/hooks/useSelector.spec.js b/test/hooks/useSelector.spec.js index b0c8692b0..47a419563 100644 --- a/test/hooks/useSelector.spec.js +++ b/test/hooks/useSelector.spec.js @@ -154,6 +154,49 @@ describe('React', () => { expect(renderedItems).toEqual([0, 1]) }) + + it('works properly with dispatch from componentDidUpdate', () => { + store = createStore(c => c + 1, -1) + + const Comp = () => { + const selector = useCallback(c => c, []) + const value = useSelector(selector) + renderedItems.push(value) + return + } + + class CompClass extends React.PureComponent { + constructor(props) { + super(props) + this.dispatched = false + } + componentDidUpdate() { + if (this.dispatched) { + return + } + store.dispatch({ type: '' }) + this.dispatched = true + } + render() { + return
+ } + } + + rtl.render( + + + + ) + + // The first render doesn't trigger componentDidUpdate + expect(renderedItems).toEqual([0]) + + // This dispatch forces Comp and CompClass to re-render, + // triggering componentDidUpdate and dispatching another action + store.dispatch({ type: '' }) + + expect(renderedItems).toEqual([0, 1, 2]) + }) }) describe('performance optimizations and bail-outs', () => {