How to stop a form from submitting multiple times, even on slower network?

I have been developing an app recently, and during the testing I found some interesting bugs.. Short layout of the problem. It's a basic CRUD app, and while creating something I do that inside a form, and then I have a submit button which fires the onSubmit function. Inside the onSubmit function I do a mutation. And then in the mutation itself I redirect the user... E.g.
const Router = useRouter();

const createPostMutation = trpc.posts.create.useMutation({
onSuccess: (data) => {
Router.replace(`/my-posts/${data.id}`)
}
})

const onSubmit = () => {
createPostMutation.mutate({
title: "Title",
content: "Content"
})
}

...

<form>
...

<button type="submit" disabled={createPostMutation.isLoading}>Create post</button>
</form>

const Router = useRouter();

const createPostMutation = trpc.posts.create.useMutation({
onSuccess: (data) => {
Router.replace(`/my-posts/${data.id}`)
}
})

const onSubmit = () => {
createPostMutation.mutate({
title: "Title",
content: "Content"
})
}

...

<form>
...

<button type="submit" disabled={createPostMutation.isLoading}>Create post</button>
</form>

Now when I submit everything is created as you would normally expect. But the problem is if you have a slower connection, then while the Router is redirecting you, there is a split second where createPostMutation.isLoading is false, because it already finished, and you can in that moment click multiple times and it will create multiple posts... I also tried creating a state like wasSubmitted which becomes true in the onSuccess callback, and then disable the mutation based on that... However, not even that helps... Did anyone have the same problems and how did you solve it?
6 Replies
Thimo_o
Thimo_o15mo ago
I used react hook for my validation, OnSucces of my form I use react-hook-forms reset function and then its isValid property to disable my button. That might help although i don't know if its a complete solution
barry
barry15mo ago
Just disable the submit button after submitting
JulieCezar
JulieCezar15mo ago
@Thimo_o I will try this 👍 But I do have some forms which are too simple to include RHF, and if I just reset that state, before the changes are complete I can still submit LoL I'm already checking with
disabled={ mutation.isLoading || reactHookForm.isSubmitting || isSubmitted }
disabled={ mutation.isLoading || reactHookForm.isSubmitting || isSubmitted }
and I can still submit multiple times xd
barry
barry15mo ago
No I meant on the button
JulieCezar
JulieCezar15mo ago
Yes that disable is on button But in that split second after the mutation has succeded, but the Router is still redirecting, or modal is still closing, you can smash the submit button and it will submit again... ---- I fixed it by adding a isSubmitted state when I call the onSubmit function I immediately set it to true, and then in the onSettled callback I set it to false in case an error occured so that I cn submit again This seems to work whatever I try to break it 👍
isaac_way
isaac_way15mo ago
you can put router.replace into a mutation and check if its loading as well I think
const replaceMutation = useMutation(router.replace);
const submitMutation = useMutation(submitFn, {
onSuccess: ()=>{
replaceMutation.mutate("route")
}
)

const disabled = formMutation.isLoading || replaceMutation.isLoading;
const replaceMutation = useMutation(router.replace);
const submitMutation = useMutation(submitFn, {
onSuccess: ()=>{
replaceMutation.mutate("route")
}
)

const disabled = formMutation.isLoading || replaceMutation.isLoading;