Agree with @monim's explanation.
The reason this is happening is because setState
is asynchronous. So clientSecret may not yet hold a value when stripe.confirmCardPayment
was called. This is in line with the React docs here: https://17.reactjs.org/docs/react-component.html#setstate
React does not guarantee that the state changes are applied immediately
...
setState()
does not always immediately update the component. It may batch or defer the update until later. This makes readingthis.state
right after callingsetState()
a potential pitfall.
Another approach you can consider, is to use the useEffect
hook to monitor changes to clientSecret. This way, once it has a value/changed it's value, you can call stripe.confirmCardPayment
.
const [clientSecret, setClientSecret] = useState('');
useEffect(() => {
async function confirm() {
if (stripe && elements) {
const { error: stripeError } = await stripe.confirmCardPayment(clientSecret, {
payment_method: {
card: elements.getElement(CardElement)
}
});
if (stripeError) {
console.error('Payment failed', stripeError);
} else {
console.log('Payment successful');
}
}
}
if (clientSecret) {
confirm();
}
}, [clientSecret, setClientSecret, stripe, elements]);
const handleSubmit = async (event) => {
event.preventDefault();
await createPaymentIntent();
};
const createPaymentIntent = async () => {
var imageLength = localStorage.getItem("imageBytes").split(',').length;
await fetch(`${HostName}api/Sell/xxxxx`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ "numberOfImages": imageLength })
})
.then((response) => response.json())
.then((response) => {
setClientSecret(response.clientSecret);
})
.catch(error => console.warn(error));
};