Prevent duplicate form submissions/ throttle API calls when submitting a form in a Next.js application

In my Next.js application, I am facing an issue with the sign-up form.

The problem occurs when the user clicks the "sign up" submit button multiple times quickly, resulting in the application sending out multiple fetch requests and displaying multiple toasts on the interface.

What I want is for the user to be unable to take any actions after clicking submit until the first submission is completed.

Initially, I thought about making the API call synchronous. However, it seems that this approach is not recommended:

  • You can refer to this answer which advises against using synchronous fetch: How to make javascript fetch synchronous?

I have looked into similar questions but couldn't find a solution that worked:

  • For example, check out How to prevent form from submitting multiple times from client side?. The top answer doesn't work well with form validation and relies on JQuery.

I'm still unclear why a synchronous request is not recommended in this scenario. My goal is to stop any activity on the page until the form submission is complete.

Can you suggest the best way to prevent switch bounce during form submission and explain why?

Here is the code snippet for the sign-up page (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 )

API call function (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;
}

Answer №1

One common and effective approach is to disable the submit button until a response is received from the API. Here's an example:

Start by creating a state:

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

Utilize this state to control the disabled attribute of the submit button:

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

In your event handler function, call setIsSubmitting:

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 );

  // handle errors here

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

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

  setIsSubmitting(false);
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Having issues with accessing data from Informix database in PHP due to an undefined index?

I am encountering the following error multiple times per row: Notice: Undefined index: enviopre in /opt/lampp/htdocs/pruebax/pruebaxone.php on line 34 Notice: Undefined index: enviofra in /opt/lampp/htdocs/pruebax/pruebaxone.php on line 35 Notice: Undef ...

Creating a Typescript interface for a anonymous function being passed into a React component

I have been exploring the use of Typescript in conjunction with React functional components, particularly when utilizing a Bootstrap modal component. I encountered some confusion regarding how to properly define the Typescript interface for the component w ...

Is it not possible to access the profile page using the GET method?

I am currently using Express.js to display user input in the URL after submitting a form and redirecting the user to their profile page with their name in the URL. To achieve this, I utilized req.query and the GET method. var express = require('expre ...

The 'fs' module does not seem to have an immediate impact; a server restart may be necessary for the changes to take

This NodeJS project involves starting the server with npm start. The project reads files from a folder called "./mydir/" using 'fs.readdirSync'. It then pushes these files into an array and prints them on the console. var fs = require('fs ...

Do you think this architecture is ideal for a NodeJS recursive MongoDB archiver?

Currently, I am faced with the challenge of archiving data stored on a MongoDB server that has been operational for more than a year. The server has accumulated close to 100GB of data, with many collections containing over 10 million documents each. Unfort ...

How to position an image on top of each printed page using HTML/CSS (SCSS)

I've created a simple and small webpage that looks like this: https://i.sstatic.net/R7Ajz.png Everything is perfect in the browser, with all the styles (margin, padding, etc.) just as I want it. However, my issue lies in the print view of the page. ...

Is it possible to achieve server side rendering with Nextjs pages that utilize useEffect?

Currently, I am contemplating a switch from React to Next.js and struggling with grasping the concept of server-side rendering. My concern is that if my page includes a component utilizing the useEffect hook (such as one involving Three.js), will Next.js ...

Ways to incorporate a promise within a for loop code block

In this code snippet, my goal is to create a ranking based on the prices and nutrient content of various foods in a Wix database. The process involves calculating an index for each food item: function calculate() { var array = []; wixData.query('Food& ...

What is the best way to wait for a button's listeners to resolve in JavaScript?

Currently, I am conducting frontend tests utilizing Jest with the jsdom environment to simulate a DOM tree and manually trigger actions such as button.click(). My goal is to be able to await button.click(), which in my expectations should wait for all of ...

Managing extensive amounts of data with server-side scripting in a Datatable

I am exploring the use of the datatable plugin to effectively manage a large amount of data. Currently, I am interested in implementing "server side processing in datatables" with the help of server-side scripting. Since I have limited experience with AJA ...

tips on sending multiple data- id in a modal window

Let's say I have multiple order IDs $order_id='12345566778'; $prod_id='126778899'; $sell_id='373462562363'; When I select a particular order ID, I want to pass it to a PHP variable located in the modal body of a popup. ...

The correct way to create a Reaction Collection

I'm trying to set up an event where a user triggers a reaction with either a Check mark or X. However, I keep encountering an error that the function doesn't exist for the message object. I attempted to switch back to awaitReactions but it didn& ...

Establishing the request body for RESTful web services utilizing the POST technique

Hey there, I'm currently working on creating a REST response using the POST method. I want to pass variables dynamically instead of hardcoding them. However, I am encountering an issue when trying to send an array as a parameter to the REST web servic ...

Dynamic Loading of CSS Styles

My style-sheet is saved in this unique location: /opt/lampp/htdocs/project/core/styles/Style.css To load the CSS file using the full directory, considering that the files utilizing it are situated here: /opt/lampp/htdocs/project/client/ The ultimate ob ...

The current registry configuration does not provide support for audit requests when running npm audit

I am facing an issue with one of my dependencies that is in the form of "protobufjs": "git+https://github.com/danieldanielecki/protobufjs-angularfire.git#master". I installed it using npm install --save https://github.com/danieldanielecki/protobufjs-angula ...

What sets apart async.map from the async library and Promise.map from bluebird?

Allow me to clarify: My goal is to utilize async/await functionality with either the async or bluebird library. I'm puzzled as to why this code snippet works as expected: const promises = Promise.map (someArray, async item => { ...

How to Retrieve the Number of Requests in an Express Application

Is there a method to retrieve the overall count of requests in a specific route using Expressjs? ...

Tips for including the % symbol in the Y-axis labels on a HighChart graph

https://i.sstatic.net/Ym7Uz.png I am attempting to incorporate the % symbol after the value of 100 or -100 on the yAxis in the chart shown above. I made an attempt to add the % symbols as follows: quotes.data.frequency_counts[i].negative = Math.round(ne ...

Trialing: Uncovering stylish emotional elements using Jest/Enzyme

When I made the switch from glamorous to emotion for my project, I realized there was one important aspect missing: testing. With glamorous, I used to locate elements using selectors like this: $component.find('StyledComponent'); $component.fi ...

Numerous Bourbon Refill Opportunities

I'm currently working on a project that involves using the Bourbon Refills UI elements and I have a particular query related to modals. Specifically, I need to have multiple modals open simultaneously in a certain scenario. Here's what I'm ...