mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Fix multiple form submissions from throwing
This commit is contained in:
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user