Home > Blockchain >  Submit button in a form works after the second click. ReactJS
Submit button in a form works after the second click. ReactJS

Time:10-27

I am working on a form in React e-commerce project.

Here's how it should work: When user fills up the form and clicks the submit button I want to post the form data to a server and redirect the user to a confirmation/thank you page.

Unfortunately, when I fill up the form and click the submit button the following code works in a specific way:

1st click - it sends the data but "setSubmitted(true)" doesn't work so I am not redirected

2nd click - is sends the data again, setSubmitted works and I am redirected

Could you tell me how to fix the code?

let history = useHistory();
const [submitted, setSubmitted] = useState(false);


const handleSubmit = (e) => {

e.preventDefault();

fetch('http://localhost:8000/orders', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ cart: 1 }), //dummy data
})
  .then((response) => {
    setSubmitted(true);
    return response.json();
  })
  .then(() => {
    if (submitted) {
      return history.push('/thank-you-page');
    }
  });
};

  return (
  <form onSubmit={handleSubmit}> ... </form>
  );

CodePudding user response:

You need to remove if statement from the 2nd then(...) as the state update run asynchronously and in first time click it is false. And when you click again form submitted and then submitted is true this time from your last action and you redirected.

And one more if you are using the using data return from the first then(...) block you can put you redirect code their too and remove second one.

const handleSubmit = (e) => {

e.preventDefault();

fetch('http://localhost:8000/orders', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ cart: 1 }), //dummy data
})
  .then((response) => {
    setSubmitted(true);
    return return history.push('/thank-you-page');
  });
};

Hope this will you to fix your issue.

CodePudding user response:

setState is an asynchronous action, and will cause a re-render. So the steps that your component is going through on the first click is that it sets the state and returns the json, which means at the point that the second .then() is executed (on the first render) submitted is still false, by the second render when you click the second time the submitted is set to true from the previous click, and so it then does the history push.

Since you are only using this state to check for pushing to the next page you could replace it with a useRef, but personally I'd be inclined to re-write it like this to avoid any confusion:

const handleSubmit = async (e) => {
    e.preventDefault();
    try {
       const response = fetch('http://localhost:8000/orders', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({ cart: 1 }), //dummy data
            });
        // setSubmitted(true); // set this still if you need it elsewhere
        history.push('/thank-you-page');
        // return response.json(); // only return this if you need it to be used somewhere
    } catch(error) {
        // handleTheErrorSomehow(error)
    }
  };
  • Related