medusajs / nextjs-starter-medusa

A performant frontend ecommerce starter template with Next.js 14 and Medusa.
https://next.medusajs.com/
MIT License
1.73k stars 482 forks source link

Runtime Error in Checkout: Missing Elements Context for Stripe #205

Closed bqst closed 11 months ago

bqst commented 11 months ago

Encountered an unhandled runtime error during the checkout process when using Stripe as the payment method. The error message states:

Could not find Elements context; You need to wrap the part of your app that mounts <CardNumberElement> in an <Elements> provider.

Steps to Reproduce:

Expected Behavior:

The checkout process should proceed without any errors, allowing for successful payment completion.

Actual Behavior:

The checkout process is interrupted by a runtime error, with the StripeWrapper not being loaded due to payment_session being undefined.

luluhoc commented 11 months ago

steps to reproduce>

add to card choose address choose shipping choose stripe and then refresh the page

Unhandled Runtime Error
Error: Could not find Elements context; You need to wrap the part of your app that calls useStripe() in an <Elements> provider.

Source
src/modules/checkout/components/payment-button/index.tsx (76:26) @ useStripe

  74 | const { onPaymentCompleted } = useCheckout()
  75 |
> 76 | const stripe = useStripe()
     |                        ^
  77 | const elements = useElements()
  78 | const card = elements?.getElement("cardNumber")
  79 |
luluhoc commented 11 months ago

@bqst here is my fix

https://github.com/medusajs/nextjs-starter-medusa/pull/206

nightpoaching commented 11 months ago

211

bqst commented 11 months ago

@luluhoc Thank you for your fix, but it doesn't solve my problem. My issue is that when selecting the PaymentOption 'stripe', the Wrapper loads without a paymentSession, initiated by the Payment component here:

  // src/modules/checkout/components/payment/index.tsx#119
  ...
  useEffect(() => {
    let timeout: NodeJS.Timeout | null = null

    if (cart?.shipping_address && cart?.payment_sessions) {
      timeout = setTimeout(() => {
        initPayment()
      }, 5000)
    }

    return () => {
      if (timeout) {
        clearTimeout(timeout)
      }
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [cart])
  ...

The paymentSession is undefined until initPayment responds, and so the Wrapper does not mount StripeWrapper, which causes the problem with Stripe Elements.

VariableVic commented 11 months ago

Should be fixed in https://github.com/medusajs/nextjs-starter-medusa/pull/218. Lmk if it solves your issues!