Interview question
Prevent a duplicate form mutation
Guards a mutation immediately, exposes pending state, and restores the command after failure.
TL;DR
Guards a mutation immediately, exposes pending state, and restores the command after failure.
Synchronous guards, pending UI, retries, idempotency keys, and accessible feedback.
Practice the problem like a real interview: restate, reason, implement, and test.
The save command may take several seconds. Prevent duplicate calls before React renders the disabled state, while allowing retry after failure.
Two rapid submit events produce one fetch call and one stable idempotency key.
A ref closes the tiny gap before the pending render. State communicates progress; the ref enforces the invariant. The server key remains the final protection against retries outside this component.
const submittingRef = useRef(false);
const [pending, setPending] = useState(false);
async function submit(event: FormEvent) {
event.preventDefault();
if (submittingRef.current) return;
submittingRef.current = true;
setPending(true);
const key = crypto.randomUUID();
try {
await api.createOrder(values, { idempotencyKey: key });
} finally {
submittingRef.current = false;
setPending(false);
}
}
return <button type="submit" disabled={pending} aria-busy={pending}>
{pending ? "Creating order" : "Create order"}
</button>;
The client guard improves UX; database-backed idempotency provides correctness if the browser retries after an uncertain response.
Move to the linked follow-up, next path step, prerequisite, or deeper variant.
Practice the next layer of the same subject.