pelotador.1
pelotador.1

Reputation: 380

dispatching multiple api calls that depend on each other

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

Answers (1)

Kaneki21
Kaneki21

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

Related Questions