From 11db31a58ec2093a0bb606938a75a3ab92372e89 Mon Sep 17 00:00:00 2001 From: axel Date: Sun, 1 Mar 2020 18:26:06 -0600 Subject: [PATCH] Fix useSelector race condition when dispatch happens in componentDidUpdate --- src/hooks/useSelector.js | 8 +++---- test/hooks/useSelector.spec.js | 43 ++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 5 deletions(-) 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', () => {