#Ludvig-useStripe

1 messages ยท Page 1 of 1 (latest)

rotund veldt
#

Not seeing a way to get around that. Why are you trying to do it without an Elements Provider?

potent sparrow
#

I'm not trying to go without the <Elements>, I would like to access the const stripe = useStripe() in the same component as where I have <Elements>.

Maybe I have a solution.
I'm not too good at react though.

Can I render some other components inside of <Elements> before I have provided <Elements> with data? I will provide <Elements> with necessary data before I render out the <PaymentElement />

Or will no children of <Elements> be rendered until <Elements> have been provided with data?

rotund veldt
#

Hey, apologies for the silence. I am still looking in to this. Not too great at reach either. I will reach out to colleagues to see what is possible here

#

So what is the use case where you need to render them without data? What data do you not have when you are initializing here?

potent sparrow
#

Well I'm trying to have a checkoutpage with a form. The form will collect all necessary details in a few steps. Completing one step will unlock the next step. Therefore, I don't want to render out the <PaymentElement /> until the rest have been completed, which means that I don't want to supply the <Elements> with any data until it's time to render the <PaymentElement />

#

I'll supply you with more information in a little while

harsh cloak
#

๐Ÿ‘‹ I'm taking over for @rotund veldt so I can take a look soon

potent sparrow
#

bumping so the thread doesn't close yet

harsh cloak
#

I am so sorry - crazy day

#

@sinful chasm is also hopping in soon!

solid monolith
#

Hey @potent sparrow we meet again ๐Ÿ˜„
karbi had to hop off but I can take a look

potent sparrow
#

Btw, did you get any information on the last issue I had, you messaged some people in the dev team?

solid monolith
#

I have not. I'm watching the ticket though. def a chromium bug.

#

could you walk me through your component hierarchy?

potent sparrow
solid monolith
#

sure thing!

potent sparrow
sinful chasm
#

I don't want to render out the <PaymentElement /> until the rest have been completed, which means that I don't want to supply the <Elements> with any data until it's time to render the <PaymentElement />

For this, you should be able to conditionally render the payment element even with Elements fully ready, right?

potent sparrow
sinful chasm
#

Yea Elements needs to be ready for that to works

#

if you have as issue with something like circular logic there you might want to shift the react tree around to have only the payment element as a child to the elements provider

#

ie if the Elements parameters for the payment depend on some other choice, that choice can't live inside the elements component

potent sparrow
#

When going to the checkoutPage I will build the functionality so that you complete steps:

  1. Cart
  2. Address
  3. Shipping option
  4. Payment Option (fetch api to send amount to server and recieve clientSecret, provide it to <Elements> with data here or in 4.1)
    4.1 Stripe Payment gets chosen - Render the <PaymentElement>
    4.2 Fill out the Payment Element with card details
  5. Press "purchase" button (submit form)

As of now, the "steps" doesn't have to work, it's fine to just render everything straight away, but in order for me to handle the form submit, I need the const stripe = useStripe(), const elements = useElements() to use in the handleFormSubmit, therefore they will all be in the same component. This means that I can't wrap the component that calls useStripe in the <Elements> providers. Does this make sense?

#

I believe that is my issue, I'm not sure how to handle my formSubmit if I can't access the stripe and elements in there as I need them to confirm the payment

solid monolith
#

all of the above is part of one form component?

potent sparrow
#

Well, I guess I can extract some logic and put it somewhere else, but I'm not sure if it matters. The fact that I need to access the elements and stripe inside my handleFormSubmit means that I can't wrap the component that calls useStripe in <Element> providers

#
  export default function CheckoutPage() {
  const stripe = useStripe();
  const elements = useElements();
  function handleSubmit() { /* is using stripe and elements to confirm payment */ };
  return (
  <form onSubmit={handleSubmit}>
    <cart />
    <address />
    <shipping />
    <payments>
      <Elements stripe={stripePromise} options={options}>
        <PaymentElement />
      </Elements>
    </payments>
    <button type="submit" />
  </form>
  )}
#

Does this make it easier?

sinful chasm
#

The fundamental issue with that useStripe can't be used outside of an Elements context -- Elements is the provider that supplies the stripe instance

#

Are you actually using the form logic aside from the submit handler?

potent sparrow
#

I'm doing preventDefault on my handleSubmit anyways

sinful chasm
#

ie, you might instead switch to a SubmitPayment component (instead the Elements context) that can useStripe internally and also submit all your local form data, assuming its in some central state somewhere

#
export default function CheckoutPage() {
  const elements = useElements();
  return (
  <div>
    <cart />
    <address />
    <shipping />
    <payments>
      <Elements stripe={stripePromise} options={options}>
        <PaymentElement />
        <SubmitForm>
      </Elements>
    </payments>
  </div>
  )}
export default function SubmitForm() {
  const stripe = useStripe();
  
  function handleSubmit() { /* is using stripe and elements to confirm payment */ };
  return (
  <button onClick={handleSubmit} />
  )}

#

something like that?

potent sparrow
#

I'll need some time to think about it and I'll try to build it out to try, but you might be right.

Can you briefly explain when a form is really needed, as you were wondering if I was using the form logic? You're right that I'm collecting data from inputs with state, and so I'm not sure what the <form> is really for? Maybe I don't need to use it? I'm using it probably just to set <form onSubmit={handleSubmit)> and the fact that it feels like it's a form I'm building

#

I apologize that it's not an entirely stripe related question but I hope it's fine in this context

sinful chasm
#

You'd only need the form if you were actually using it to structure the data for the request to your server -- most react app dont actually do this

#

there is also some semantic convetion, you can keep the form wrapper and use your own submission handler

potent sparrow
#

Thanks! I'll try to build and try out your proposed solution and I'll get back in a bit if it works or if I face some issues

sinful chasm
#

Sounds good ๐Ÿ™‚

potent sparrow
#

What I want to achieve is this

#

The "slutfรถr kรถp" button is the purchase/submit button

#

And as you see with the structure I've done it wouldn't be the same to have the button right under the PaymentElement

#

together with the <payments>

#

The picture is using this structure (but the submit button obviously doesn't work)

  export default function CheckoutPage() {
  const stripe = useStripe();
  const elements = useElements();
  function handleSubmit() { /* is using stripe and elements to confirm payment */ };
  return (
  <form onSubmit={handleSubmit}>
    <cart />
    <address />
    <shipping />
    <payments>
      <Elements stripe={stripePromise} options={options}>
        <PaymentElement />
      </Elements>
    </payments>
    <button type="submit" />
  </form>
  )}
sinful chasm
#

Sure, if you invert payments/Elements:

<Elements stripe={stripePromise} options={options}>
  <payments>
    <PaymentElement />
  </payments>
  <SubmitForm>
</Elements>    
potent sparrow
#

Can I somehow have the button onClick which is outside <payments> to trigger a submit function inside <payments>?

sinful chasm
#

submit function inside <payments>
not sure what this means, but i think it should enable you to do what you need