diff --git a/packages/react-reconciler/src/ReactFiberHooks.new.js b/packages/react-reconciler/src/ReactFiberHooks.new.js index b195a0cb57488..ea4312394c87b 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.new.js +++ b/packages/react-reconciler/src/ReactFiberHooks.new.js @@ -821,7 +821,9 @@ function updateReducer( newState = ((update.eagerState: any): S); } else { const action = update.action; - newState = reducer(newState, action); + const reducerImpl = + update.eagerReducer !== null ? update.eagerReducer : reducer; + newState = reducerImpl(newState, action); } } update = update.next; diff --git a/packages/react-reconciler/src/ReactFiberHooks.old.js b/packages/react-reconciler/src/ReactFiberHooks.old.js index 7c51c43ad2e7e..e2be5a96d5c97 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.old.js +++ b/packages/react-reconciler/src/ReactFiberHooks.old.js @@ -821,7 +821,9 @@ function updateReducer( newState = ((update.eagerState: any): S); } else { const action = update.action; - newState = reducer(newState, action); + const reducerImpl = + update.eagerReducer !== null ? update.eagerReducer : reducer; + newState = reducerImpl(newState, action); } } update = update.next; diff --git a/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js b/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js index fc5e61cd78ee6..a8940c781bd10 100644 --- a/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js +++ b/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js @@ -3784,4 +3784,49 @@ describe('ReactHooksWithNoopRenderer', () => { expect(Scheduler).toHaveYielded(['Render: 0']); }); + + it('reducer-closure', () => { + let setLimit; + let increment; + function Test() { + const [limit, _setLimit] = useState(5); + const [count, _increment] = useReducer((state, action) => { + return state < limit ? state + 1 : state; + }, 1); + setLimit = _setLimit; + increment = _increment; + + return ; + } + + act(() => { + ReactNoop.render(); + }); + + expect(Scheduler).toHaveYielded(['Render: 1']); + + act(() => { + increment(); + increment(); + increment(); + increment(); + }); + + expect(Scheduler).toHaveYielded(['Render: 5']); + + act(() => { + increment(); + }); + act(() => { + increment(); + }); + + expect(Scheduler).toHaveYielded([]); + + act(() => { + setLimit(10); + }); + + expect(Scheduler).toHaveYielded(['Render: 5']); + }); });