Fix multiple form submissions from throwing

This commit is contained in:
Matt Carroll
2025-04-29 15:25:54 -07:00
parent 88b9767404
commit c4b0701ec7
2 changed files with 43 additions and 1 deletions
+42
View File
@@ -1670,6 +1670,48 @@ describe('ReactDOMForm', () => {
expect(divRef.current.textContent).toEqual('Current username: acdlite');
});
it.only('multiple form submissions in rapid succession do not throw', async () => {
const submitFormTwiceButtonRef = React.createRef();
let actionCounter = 0;
function App() {
const formRef = React.createRef();
// Submits the form twice in quick succession
// This simulates a user clicking a button twice in rapid succession
async function submitFormTwice() {
formRef.current.requestSubmit();
await new Promise(res => setTimeout(res, 1));
formRef.current.requestSubmit();
}
// This is a userspace action. it must take a non-zero amount of time to
// allow the form to be submitted again before the first one finishes.
// Otherwise, the form transitions will be batched and will not run concurrently.
async function submitForm() {
actionCounter++;
return new Promise(res => setTimeout(res, 1));
}
return (
<>
<form ref={formRef} action={submitForm}>
<button type="submit">Submit</button>
</form>
<button ref={submitFormTwiceButtonRef} onClick={submitFormTwice}>
Submit twice
</button>
</>
);
}
const root = ReactDOMClient.createRoot(container);
await act(() => root.render(<App />));
await act(async () => {
submitFormTwiceButtonRef.current.click();
});
expect(actionCounter).toBe(2);
});
it(
'requestFormReset works with inputs that are not descendants ' +
'of the form element',
+1 -1
View File
@@ -3261,7 +3261,7 @@ export function startHostTransition<F>(
function ensureFormComponentIsStateful(formFiber: Fiber) {
const existingStateHook: Hook | null = formFiber.memoizedState;
if (existingStateHook !== null) {
if (existingStateHook !== null && existingStateHook.next !== null) {
// This fiber was already upgraded to be stateful.
return existingStateHook;
}