diff --git a/packages/react-dom/src/__tests__/ReactDOMForm-test.js b/packages/react-dom/src/__tests__/ReactDOMForm-test.js index 977439b099971..ea97b293ff707 100644 --- a/packages/react-dom/src/__tests__/ReactDOMForm-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMForm-test.js @@ -1295,4 +1295,52 @@ describe('ReactDOMForm', () => { assertLog(['B']); expect(container.textContent).toBe('B'); }); + + // @gate enableFormActions + // @gate enableAsyncActions + test('useFormState works in StrictMode', async () => { + let actionCounter = 0; + async function action(state, type) { + actionCounter++; + + Scheduler.log(`Async action started [${actionCounter}]`); + await getText(`Wait [${actionCounter}]`); + + switch (type) { + case 'increment': + return state + 1; + case 'decrement': + return state - 1; + default: + return state; + } + } + + let dispatch; + function App() { + const [state, _dispatch, isPending] = useFormState(action, 0); + dispatch = _dispatch; + const pending = isPending ? 'Pending ' : ''; + return ; + } + + const root = ReactDOMClient.createRoot(container); + await act(() => + root.render( + + + , + ), + ); + assertLog(['0']); + expect(container.textContent).toBe('0'); + + await act(() => dispatch('increment')); + assertLog(['Async action started [1]', 'Pending 0']); + expect(container.textContent).toBe('Pending 0'); + + await act(() => resolveText('Wait [1]')); + assertLog(['1']); + expect(container.textContent).toBe('1'); + }); }); diff --git a/packages/react-reconciler/src/ReactFiberHooks.js b/packages/react-reconciler/src/ReactFiberHooks.js index 75acffc1b9a11..46a21cf364b06 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.js +++ b/packages/react-reconciler/src/ReactFiberHooks.js @@ -2259,6 +2259,8 @@ function rerenderFormState( ); } + updateWorkInProgressHook(); // State + // This is a mount. No updates to process. const state: Awaited = stateHook.memoizedState;