From e25e27eca831432cebf457f1910fae1c02ae52e7 Mon Sep 17 00:00:00 2001 From: Imre Osswald Date: Fri, 30 Nov 2018 16:02:19 +0100 Subject: [PATCH] Fix bug in cloneHook (#14364) * Fixes #14360 and adds a test for mixed priority dispatches. It was broken because `cloneHook` assigned `memoizedState` instead of `baseState` from the original hook to `baseState` of the clone. * tweak comments --- .../react-reconciler/src/ReactFiberHooks.js | 2 +- ...eactHooksWithNoopRenderer-test.internal.js | 33 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/packages/react-reconciler/src/ReactFiberHooks.js b/packages/react-reconciler/src/ReactFiberHooks.js index 3d6de1be19777..5122a8dda4a0e 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.js +++ b/packages/react-reconciler/src/ReactFiberHooks.js @@ -253,7 +253,7 @@ function cloneHook(hook: Hook): Hook { return { memoizedState: hook.memoizedState, - baseState: hook.memoizedState, + baseState: hook.baseState, queue: hook.queue, baseUpdate: hook.baseUpdate, diff --git a/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.internal.js b/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.internal.js index 36030a2124390..ea5672147464c 100644 --- a/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.internal.js @@ -565,6 +565,39 @@ describe('ReactHooksWithNoopRenderer', () => { ReactNoop.flush(); expect(ReactNoop.getChildren()).toEqual([span('Count: 8')]); }); + + // Regression test for https://github.com/facebook/react/issues/14360 + it('handles dispatches with mixed priorities', () => { + const INCREMENT = 'INCREMENT'; + + function reducer(state, action) { + return action === INCREMENT ? state + 1 : state; + } + + function Counter(props, ref) { + const [count, dispatch] = useReducer(reducer, 0); + useImperativeMethods(ref, () => ({dispatch})); + return ; + } + + Counter = forwardRef(Counter); + const counter = React.createRef(null); + ReactNoop.render(); + + ReactNoop.flush(); + expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); + + counter.current.dispatch(INCREMENT); + counter.current.dispatch(INCREMENT); + counter.current.dispatch(INCREMENT); + ReactNoop.flushSync(() => { + counter.current.dispatch(INCREMENT); + }); + expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]); + + ReactNoop.flush(); + expect(ReactNoop.getChildren()).toEqual([span('Count: 4')]); + }); }); describe('useEffect', () => {