#Ludvig-useStripe
1 messages ยท Page 1 of 1 (latest)
Not seeing a way to get around that. Why are you trying to do it without an Elements Provider?
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?
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?
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
๐ I'm taking over for @rotund veldt so I can take a look soon
bumping so the thread doesn't close yet
Hey @potent sparrow we meet again ๐
karbi had to hop off but I can take a look
Hello Hanzo ๐ Yes, I'll try to provide more details too, but maybe you can get an understanding of what I'm trying to do just from reading the previous messages
Btw, did you get any information on the last issue I had, you messaged some people in the dev team?
I have not. I'm watching the ticket though. def a chromium bug.
could you walk me through your component hierarchy?
Alright! If you happen to see anything in regards to that ticket, and you remember my name, could you send me a brief update on it whenever something happens? ๐
sure thing!
Sure, I'll need some time to sort this out. I'll speak to you soon
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?
Yes, I believe so - I'll try to explain further in a bit, but check the previous message to that one
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
When going to the checkoutPage I will build the functionality so that you complete steps:
- Cart
- Address
- Shipping option
- 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 - 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
all of the above is part of one form component?
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?
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?
I'm not sure if I do
I'm doing preventDefault on my handleSubmit anyways
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?
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
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
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
Sounds good ๐
In this message you wrote
export default function CheckoutPage() {
const elements = useElements();
return (
<div>
<cart />
<address />
<shipping />
<payments>
<Elements stripe={stripePromise} options={options}>
<PaymentElement />
<SubmitForm>
</Elements>
</payments>
</div>
)}
Is there no way of placing the <SubmitForm> component outside of the <payments>?
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>
)}
Sure, if you invert payments/Elements:
<Elements stripe={stripePromise} options={options}>
<payments>
<PaymentElement />
</payments>
<SubmitForm>
</Elements>
Can I somehow have the button onClick which is outside <payments> to trigger a submit function inside <payments>?
I'll try this
submit function inside <payments>
not sure what this means, but i think it should enable you to do what you need