Skip to content

Commit be58f26

Browse files
Fix multiple form submissions from throwing
1 parent 8e9a5fc commit be58f26

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

packages/react-dom/src/__tests__/ReactDOMForm-test.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1670,6 +1670,48 @@ describe('ReactDOMForm', () => {
16701670
expect(divRef.current.textContent).toEqual('Current username: acdlite');
16711671
});
16721672

1673+
it.only('multiple form submissions in rapid succession do not throw', async () => {
1674+
const submitFormTwiceButtonRef = React.createRef();
1675+
let actionCounter = 0;
1676+
function App() {
1677+
const formRef = React.createRef();
1678+
// Submits the form twice in quick succession
1679+
// This simulates a user clicking a button twice in rapid succession
1680+
async function submitFormTwice() {
1681+
formRef.current.requestSubmit();
1682+
await new Promise(res => setTimeout(res, 1));
1683+
formRef.current.requestSubmit();
1684+
}
1685+
1686+
// This is a userspace action. it must take a non-zero amount of time to
1687+
// allow the form to be submitted again before the first one finishes.
1688+
// Otherwise, the form transitions will be batched and will not run concurrently.
1689+
async function submitForm() {
1690+
actionCounter++;
1691+
return new Promise(res => setTimeout(res, 1));
1692+
}
1693+
1694+
return (
1695+
<>
1696+
<form ref={formRef} action={submitForm}>
1697+
<button type="submit">Submit</button>
1698+
</form>
1699+
<button ref={submitFormTwiceButtonRef} onClick={submitFormTwice}>
1700+
Submit twice
1701+
</button>
1702+
</>
1703+
);
1704+
}
1705+
1706+
const root = ReactDOMClient.createRoot(container);
1707+
await act(() => root.render(<App />));
1708+
1709+
await act(async () => {
1710+
submitFormTwiceButtonRef.current.click();
1711+
});
1712+
expect(actionCounter).toBe(2);
1713+
});
1714+
16731715
it(
16741716
'requestFormReset works with inputs that are not descendants ' +
16751717
'of the form element',

packages/react-reconciler/src/ReactFiberHooks.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3261,7 +3261,7 @@ export function startHostTransition<F>(
32613261

32623262
function ensureFormComponentIsStateful(formFiber: Fiber) {
32633263
const existingStateHook: Hook | null = formFiber.memoizedState;
3264-
if (existingStateHook !== null) {
3264+
if (existingStateHook !== null && existingStateHook.next !== null) {
32653265
// This fiber was already upgraded to be stateful.
32663266
return existingStateHook;
32673267
}

0 commit comments

Comments
 (0)