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