1

I have a sign-up form in my Next.js application.

Undesired behaviour: if the user clicks the "sign up" submit button multiple times in quick succession, then the application makes multiple fetch requests, and multiple toasts are shown on the interface.

Desired behaviour: The user should not be able to perform any actions after pressing submit until the first submit is complete.

My first though was to make the API call synchronous. But for reasons I don't fully understand, this seems to be regarded as a bad idea:

I've looked at other questions along similar lines but the answers did not help:

I don't quite understand why a synchronous request is not best practice here. Sure I'm blocking the CPU during an I/O operation, but I don't want the page to be doing anything until the form submission is complete?

What is the recommended method for preventing switch bounce on the form submission and could you explain why?

src/pages/auth/sign-up.js:

const onSubmit = async (data) => {
  const { email, password1, password2, first_name, last_name } = data;

  const response = await postSignUp( email, password1, password2, first_name, last_name );

  // error handling code

  toast.success('You have successfully registered!', { autoClose: 2500 })

  setTimeout( () => {
    router.push({ pathname: '/auth/verify-email', query: { email: email } });
  }, 2500 )

/src/lib/api.js:

export async function postSignUp(email, password1, password2, first_name, last_name) {
  const response = await fetch(SIGN_UP_ENDPOINT, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify( { email, password1, password2, first_name, last_name } ),
  });

  const json = await response.json();
  return json;
}
Neil
  • 3,020
  • 4
  • 25
  • 48

1 Answers1

2

A very simple and generally used method is to make the submit button be disabled until you get a response back from your API. So, for example:

Create a state:

const [isSubmitting, setIsSubmitting] = useState(false);

Use that state to set your submit button's disabled attribute:

<button type="submit" disabled={isSubmitting}>Save</button>

Call setIsSubmitting from your event handler:

const onSubmit = async (data) => {
  setIsSubmitting(true);

  const { email, password1, password2, first_name, last_name } = data;

  const response = await postSignUp( email, password1, password2, first_name, last_name );

  // error handling code

  toast.success('You have successfully registered!', { autoClose: 2500 })

  setTimeout( () => {
    router.push({ pathname: '/auth/verify-email', query: { email: email } });
  }, 2500 )

  setIsSubmitting(false);
}
ruohola
  • 21,987
  • 6
  • 62
  • 97
  • 1
    I should have included the //error handling code since I needed to add "setIsSubmitting(false);" at the end of that so as to avoid getting the same problem of not being able to submit ever after server validation fails. But that's my bad the answer is great otherwise and fairly clear how to add to the //error handling code thank you. – Neil Feb 25 '22 at 11:50