Reputation: 380
I'm working on a project where I need multiple APIs to be dispatched on the click of my placeOrderHandler
. The issue that I'm having is that some of these dispatches depend on a previously listed dispatch being completed. Additionally, I get an error stating
Uncaught (in promise) IntegrationError: Invalid value for stripe.confirmCardPayment intent secret: value should be a client_secret string
If I haven't received client_secret
in the frontend by the time
const {error: stripeError, paymentIntent} = await stripe.confirmCardPayment(client_secret
is called. I tried using conditional statements andsetTimeout()
to fix this issue. However, I'm having some issues. I've also never done this, so I'm not even sure if I have set this up correctly. The main issue that I'm having is that if the if
statement is true and the setTimeout()
starts once it ends it just loads back the PlaceOrderScreen.js
(the screen where placeOrderHandler
is), and then does nothing. How would I get this to repeat until the if
statement is false and the else
statement is therefore true? I would really appreciate any help or advice on how to fix this and if there is a better and more efficient way of doing this. Thank you!
const paymentCreate = useSelector((state) => state.paymentCreate);
const {client_secret } = paymentCreate;
const elements = useElements();
const stripe = useStripe();
const placeOrderHandler = async (e) => {
e.preventDefault();
if (!stripe || !elements) {
return;
}
const paymentMethodType = 'card';
const currency = 'usd';
const {error: backendError} = dispatch(payment(paymentMethodType, currency, cart, userId, ))
if(client_secret.length === 0){
setNotLoaded(true);
setTimeout(() => {
setNotLoaded(false);
console.log(client_secret.length)
}, 30000);}
else if(client_secret.length > 0){
const {error: stripeError, paymentIntent} = await stripe.confirmCardPayment(client_secret,
{
payment_method: {
card: elements.getElement(CardNumberElement),
billing_details: {
name: cart.billingAddress.fullName,
},
},
},
)
if (stripeError) {
console.log('stripeError')
return;
}
if (backendError) {
console.log(backendError)
return;
}
dispatch(createOrder({ ...cart, orderItems: cart.cartItems }))
setNotLoaded(true);
setTimeout(() => {
setNotLoaded(false);
const orderId = order._id
dispatch(paymentInfo(orderId))
if (success) {
const email = userInfo.email
dispatch(shippingTransaction({shippingMethod, shipment, orderId}))
.then((shippingMethod) => dispatch(emailOrder(email)))
if (!order.paymentMethod.fullName) {
setNotLoaded(true);
setTimeout(() => {
setNotLoaded(false);
props.history.push(`/order/${order._id}`)
dispatch({ type: ORDER_CREATE_RESET })
}, 10000);}
else {
props.history.push(`/order/${order._id}`)
dispatch({ type: ORDER_CREATE_RESET })
}
}
}, 10000);
}
};
Upvotes: 0
Views: 637
Reputation: 1420
setTimeout is not the correct approach, for waiting you have to use await or then-catch block(Promise handling). As per my understanding you are using Redux so you can trigger dispatch in useEffect(you would only want to get the client_secrect once) and then use useSelector for accessing the client_secret from the store and then it should be accessible
Upvotes: 1