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