I am working on a ReactJS project where I want to integrate stripe to allow users to update their payment information for a subscription.
I am following the guide at https://stripe.com/docs/stripe-js/react but I am hitting an issue.
Below is the code that I currently have
const stripe = useStripe();
const elements = useElements();
const errorDialogueCleared = () => {
setAPIResult(null);
}
const stripePromise = loadStripe('my_test_key');
const baseStripeElementOptions = {
style: {
base: {
fontFamily: 'Oxanium',
fontSize: '16px',
color: '#000000',
'::placeholder': {
color: '#000000',
},
},
invalid: {
color: '#9e2146',
},
}
}
const handleSubmit = async (event) => {
// Block native form submission.
event.preventDefault();
if (!stripe || !elements) {
// Stripe.js has not loaded yet. Make sure to disable
// form submission until Stripe.js has loaded.
return;
}
// Get a reference to a mounted CardElement. Elements knows how
// to find your CardElement because there can only ever be one of
// each type of element.
const cardElement = elements.getElement(CardElement);
// Use your card Element with other Stripe.js APIs
const {error, paymentMethod} = await stripe.createPaymentMethod({
type: 'card',
card: cardElement,
});
if (error) {
console.log('[error]', error);
} else {
console.log('[PaymentMethod]', paymentMethod);
}
};
return (
<div className='container-fluid'>
<div className="mainContentNoSidebar">
<TopNavBar displayTimePeriodButton={false} title='Update Account Information' />
<BreadcrumbNav menu_items={breadcrumbNav} />
<div className='contentWrapper'>
<div className='container'>
<h1>Update Account Information</h1>
<form onSubmit={handleSubmit} style={{width: '50%', marginLeft: 'auto', marginRight: 'auto'}}>
<Elements stripe={stripePromise}>
<CardElement options={baseStripeElementOptions} />
</Elements>
<button className='btn btn-primary'>Submit Payment Details</button>
</form>
</div>
</div>
</div>
<ErrorDialogue dialogClosed={errorDialogueCleared} api_result={currentError} />
</div>
)
}
However, although it feels like I've followed the documentation I am getting the following error as soon as the page loads:
Error: Could not find Elements context; You need to wrap the part of your app that calls useStripe() in an provider
My CardElement is wrapped in an Elements components so I'm not sure why I am seeing this error.
You cannot call useElements unless you're already have the correct stripe context.
This means that your whole component you're showing here should be wrapped by Elements and not just the CardElement.
It should like this:
import {Elements} from '@stripe/react-stripe-js';
import {loadStripe} from '@stripe/stripe-js';
const stripePromise = loadStripe('STRIPE_PUBLISHABLE_API_KEY');
const Wrapper = (props) => (
<Elements stripe={stripePromise}>
<MyComponent {...props} />
</Elements>
);
const MyComponent = (props) => {
const stripe = useStripe();
const elements = useElements();
// rest of the component
};
Just put your component into a Parent Component, which is wrapped in the Elements Tag:
import React from "react";
import {Elements} from '@stripe/react-stripe-js';
import {loadStripe} from '@stripe/stripe-js';
import ChildComponent from './ChildComponent'
const ParentComponent= () => (
<Elements stripe={stripePromise}>
<ChildComponent />
</Elements>
);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With