We have decided to rename, rework, and move this project. We have no plans for
any additional major releases of react-stripe-elements. If you have an issue with this package, please open it on the react-stripe-js repo.
If you are starting a new Stripe integration or are looking to update your existing integration, use React Stripe.js.
- Learn to accept a payment (with React Stripe.js!)
- Migrate from
react-stripe-elementsto React Stripe.js
react-stripe-elements
React components for Stripe.js and Stripe Elements
This project is a thin React wrapper around Stripe.js and Stripe Elements. It allows you to add Elements to any React app, and manages the state and lifecycle of Elements for you.
The Stripe.js / Stripe Elements API reference goes into more detail on the various customization options for Elements (e.g. styles, fonts).
Table of Contents
- Demo
- Installation
- Getting started
- Advanced integrations
- Component reference
- Troubleshooting
- Development
Demo
The fastest way to start playing around with react-stripe-elements is with
this JSFiddle: https://jsfiddle.net/f5wxprnc/.
You can also play around with the demo locally. The source code is in demo/. To run it:
git clone https://github.com/stripe/react-stripe-elements cd react-stripe-elements # (make sure you have yarn installed: https://yarnpkg.com/) yarn install yarn run demo
Now go to http://localhost:8080/ to try it out!
⚠️
PaymentRequestButtonElementwill not render unless the page is served over HTTPS. To demoPaymentRequestButtonElement, you can tunnel over HTTPS to the local server using ngrok or a similar service.
Installation
First, install react-stripe-elements.
Install with yarn:
yarn add react-stripe-elements
OR with npm:
npm install --save react-stripe-elements
OR using UMD build (exports a global ReactStripeElements object);
<script src="https://unpkg.com/react-stripe-elements@latest/dist/react-stripe-elements.min.js"></script>
Then, load Stripe.js in your application:
<script src="https://js.stripe.com/v3/"></script>
Getting started
The Stripe context (StripeProvider)
In order for your application to have access to
the Stripe object,
let's add StripeProvider to our root React App component:
// index.js import React from 'react'; import {render} from 'react-dom'; import {StripeProvider} from 'react-stripe-elements'; import MyStoreCheckout from './MyStoreCheckout'; const App = () => { return ( <StripeProvider apiKey="pk_test_12345"> <MyStoreCheckout /> </StripeProvider> ); }; render(<App />, document.getElementById('root'));
Element groups (Elements)
Next, when you're building components for your checkout form, you'll want to
wrap the Elements component around your form. This groups the set of Stripe
Elements you're using together, so that we're able to pull data from groups of
Elements when you're tokenizing.
// MyStoreCheckout.js import React from 'react'; import {Elements} from 'react-stripe-elements'; import InjectedCheckoutForm from './CheckoutForm'; class MyStoreCheckout extends React.Component { render() { return ( <Elements> <InjectedCheckoutForm /> </Elements> ); } } export default MyStoreCheckout;
Setting up your payment form (injectStripe)
Use the injectStripe Higher-Order Component (HOC) to build your payment
form components in the Elements tree. The Higher-Order Component
pattern in React can be unfamiliar to those who've never seen it before, so
consider reading up before continuing. The injectStripe HOC provides the
this.props.stripe and this.props.elements properties that manage your
Elements groups. Within an injected component, you can call any of the methods
on the Stripe or Elements objects.
⚠️ NOTE
injectStripecannot be used on the same element that renders theElementscomponent; it must be used on the child component ofElements.injectStripereturns a wrapped component that needs to sit under<Elements>but above any code where you'd like to accessthis.props.stripe.
// CheckoutForm.js import React from 'react'; import {injectStripe} from 'react-stripe-elements'; import AddressSection from './AddressSection'; import CardSection from './CardSection'; class CheckoutForm extends React.Component { handleSubmit = (ev) => { // We don't want to let default form submission happen here, which would refresh the page. ev.preventDefault(); // Use Elements to get a reference to the Card Element mounted somewhere // in your <Elements> tree. Elements will know how to find your Card Element // because only one is allowed. // See our getElement documentation for more: // https://stripe.com/docs/stripe-js/reference#elements-get-element const cardElement = this.props.elements.getElement('card'); // From here we can call createPaymentMethod to create a PaymentMethod // See our createPaymentMethod documentation for more: // https://stripe.com/docs/stripe-js/reference#stripe-create-payment-method this.props.stripe .createPaymentMethod({ type: 'card', card: cardElement, billing_details: {name: 'Jenny Rosen'}, }) .then(({paymentMethod}) => { console.log('Received Stripe PaymentMethod:', paymentMethod); }); // You can also use confirmCardPayment with the PaymentIntents API automatic confirmation flow. // See our confirmCardPayment documentation for more: // https://stripe.com/docs/stripe-js/reference#stripe-confirm-card-payment this.props.stripe.confirmCardPayment('{PAYMENT_INTENT_CLIENT_SECRET}', { payment_method: { card: cardElement, }, }); // You can also use confirmCardSetup with the SetupIntents API. // See our confirmCardSetup documentation for more: // https://stripe.com/docs/stripe-js/reference#stripe-confirm-card-setup this.props.stripe.confirmCardSetup('{PAYMENT_INTENT_CLIENT_SECRET}', { payment_method: { card: cardElement, }, }); // You can also use createToken to create tokens. // See our tokens documentation for more: // https://stripe.com/docs/stripe-js/reference#stripe-create-token // With createToken, you will not need to pass in the reference to // the Element. It will be inferred automatically. this.props.stripe.createToken({type: 'card', name: 'Jenny Rosen'}); // token type can optionally be inferred if there is only one Element // with which to create tokens // this.props.stripe.createToken({name: 'Jenny Rosen'}); // You can also use createSource to create Sources. // See our Sources documentation for more: // https://stripe.com/docs/stripe-js/reference#stripe-create-source // With createSource, you will not need to pass in the reference to // the Element. It will be inferred automatically. this.props.stripe.createSource({ type: 'card', owner: { name: 'Jenny Rosen', }, }); }; render() { return ( <form onSubmit={this.handleSubmit}> <AddressSection /> <CardSection /> <button>Confirm order</button> </form> ); } } export default injectStripe(CheckoutForm);
Using individual *Element components
Now, you can use individual *Element components, such as CardElement, to
build your form.
// CardSection.js import React from 'react'; import {CardElement} from 'react-stripe-elements'; class CardSection extends React.Component { render() { return ( <label> Card details <CardElement style={{base: {fontSize: '18px'}}} /> </label> ); } } export default CardSection;
Using the PaymentRequestButtonElement
The Payment Request Button lets you collect payment and address information from your customers using Apple Pay and the Payment Request API.
To use the PaymentRequestButtonElement you need to first create a
PaymentRequest object.
You can then conditionally render the PaymentRequestButtonElement based on the
result of paymentRequest.canMakePayment and pass the PaymentRequest Object
as a prop.
class PaymentRequestForm extends React.Component { constructor(props) { super(props); // For full documentation of the available paymentRequest options, see: // https://stripe.com/docs/stripe.js#the-payment-request-object const paymentRequest = props.stripe.paymentRequest({ country: 'US', currency: 'usd', total: { label: 'Demo total', amount: 1000, }, }); paymentRequest.on('token', ({complete, token, ...data}) => { console.log('Received Stripe token: ', token); console.log('Received customer information: ', data); complete('success'); }); paymentRequest.canMakePayment().then((result) => { this.setState({canMakePayment: !!result}); }); this.state = { canMakePayment: false, paymentRequest, }; } render() { return this.state.canMakePayment ? ( <PaymentRequestButtonElement paymentRequest={this.state.paymentRequest} className="PaymentRequestButton" style={{ // For more details on how to style the Payment Request Button, see: // https://stripe.com/docs/elements/payment-request-button#styling-the-element paymentRequestButton: { theme: 'light', height: '64px', }, }} /> ) : null; } } export default injectStripe(PaymentRequestForm);
Advanced integrations
The above Getting started section outlines the most common integration, which makes the following assumptions:
- The Stripe.js script is loaded before your application's code.
- Your code is only run in a browser environment.
- You don't need fine-grained control over the Stripe instance that
react-stripe-elementsuses under the hood.
When all of these assumptions are true, you can pass the apiKey prop to
<StripeProvider> and let react-stripe-elements handle the rest.
When one or more of these assumptions doesn't hold true for your integration,
you have another option: pass a Stripe instance as the stripe prop to
<StripeProvider> directly. The stripe prop can be either null or the
result of using Stripe(apiKey, options) to construct a [Stripe instance].
We'll now cover a couple of use cases which break at least one of the assumptions listed above.
Loading Stripe.js asynchronously
Loading Stripe.js asynchronously can speed up your initial page load, especially if you don't show the payment form until the user interacts with your application in some way.
<html> <head> <!-- ... --> <!-- Note the 'id' and 'async' attributes: --> <!-- ┌────────────┐ ┌───┐ --> <script id="stripe-js" src="https://js.stripe.com/v3/" async></script> <!-- ... --> </head> <!-- ... --> </html>
Initialize this.state.stripe to null in the constructor, then update it in
componentDidMount when the script tag has loaded.
class App extends React.Component { constructor() { super(); this.state = {stripe: null}; } componentDidMount() { if (window.Stripe) { this.setState({stripe: window.Stripe('pk_test_12345')}); } else { document.querySelector('#stripe-js').addEventListener('load', () => { // Create Stripe instance once Stripe.js loads this.setState({stripe: window.Stripe('pk_test_12345')}); }); } } render() { // this.state.stripe will either be null or a Stripe instance // depending on whether Stripe.js has loaded. return ( <StripeProvider stripe={this.state.stripe}> <Elements> <InjectedCheckoutForm /> </Elements> </StripeProvider> ); } }
When loading Stripe.js asynchronously, the stripe prop provided by
injectStripe will initially be null, and will update to the Stripe instance
once you pass it in to your StripeProvider. You can find a working demo of
this strategy in async.js. If you run the demo locally,
you can view it at http://localhost:8080/async/.
For alternatives to calling setStatein componentDidMount, consider using a
setTimeout(), moving the if/else statement to the constructor, or
dynamically injecting a script tag in componentDidMount. For more information,
see stripe/react-stripe-elements.
Server-side rendering (SSR)
If you're using react-stripe-elements in a non-browser environment
(React.renderToString, etc.), Stripe.js is not available. To use
react-stripe-elements with SSR frameworks, use the following instructions.
The general idea is similar to the async loading snippet from the previous
section (initialize this.state.stripe to null in constructor, update in
componentDidMount), but this time we don't have to wait for the script tag to
load in componentDidMount; we can use window.Stripe directly.
class App extends React.Component { constructor() { super(); this.state = {stripe: null}; } componentDidMount() { // Create Stripe instance in componentDidMount // (componentDidMount only fires in browser/DOM environment) this.setState({stripe: window.Stripe('pk_test_12345')}); } render() { return ( <StripeProvider stripe={this.state.stripe}> <Elements> <InjectedCheckoutForm /> </Elements> </StripeProvider> ); } }
Inside your form, <InjectedCheckoutForm />, this.props.stripe will either be
null or a valid Stripe instance. This means that it will be null when
rendered server-side, but set when rendered in a browser.
Using an existing Stripe instance
In some projects, part of the project uses React, while another part doesn't.
For example, maybe you have business logic and view logic separate. Or maybe you
use react-stripe-elements for your credit card form, but use Stripe.js APIs
directly for tokenizing bank account information.
You can use the stripe prop to get more fine-grained control over the Stripe
instance that <StripeProvider> uses. For example, if you have a stripe
instance in a Redux store that you pass to your <App /> as a prop, you can
pass that instance directly into <StripeProvider>:
class App extends React.Component { render() { return ( <StripeProvider stripe={this.props.stripe}> <Elements> <InjectedCheckoutForm /> </Elements> </StripeProvider> ); } }
As long as <App /> is provided a non-null stripe prop, this.props.stripe
will always be available within your InjectedCheckoutForm.
Component reference
<StripeProvider>
All applications using react-stripe-elements must use the <StripeProvider>
component, which sets up the Stripe context for a component tree.
react-stripe-elements uses the provider pattern (which is also adopted by
tools like react-redux and
react-intl) to scope a Stripe context
to a tree of components.
This allows configuration like your API key to be provided at the root of a
component tree. This context is then made available to the <Elements>
component and individual <*Element> components that we provide.
An integration usually wraps the <StripeProvider> around the application’s
root component. This way, your entire application has the configured Stripe
context.
Props shape
There are two distinct props shapes you can pass to <StripeProvider>.
type StripeProviderProps = | {apiKey: string, ...} | {stripe: StripeObject | null};
See Advanced integrations for more information on when to use each.
The ... above represents that this component accepts props for any option that
can be passed into Stripe(apiKey, options). For example, if you are using
Stripe Connect and want to act on behalf of a
connected account, you can pass stripeAccount="acct_123" as a property to
<StripeProvider>. This will get used just like passing stripeAccount in the
options of the Stripe constructor or like using stripe_account when your
backend calls the Stripe API directly
<Elements>
The Elements component wraps groups of Elements that belong together. In most
cases, you want to wrap this around your checkout form.
Props shape
This component accepts all options that can be passed into
stripe.elements(options) as props.
