React components for Stripe.js and Stripe Elements
npm install react-stripe-elementsWe have decided to rename, rework, and move this project. We have no plans for
any additional major releases of react-stripe-elements.
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-elements to React Stripe.js
---


> 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).
- Demo
- Installation
- First, install react-stripe-elements.
- Then, load Stripe.js in your application:
- Getting started
- The Stripe context (StripeProvider)
- Element groups (Elements)
- Setting up your payment form (injectStripe)
- Using individual *Element components
- Using the PaymentRequestButtonElement
- Advanced integrations
- Loading Stripe.js asynchronously
- Server-side rendering (SSR)
- Using an existing Stripe instance
- Component reference
-
- Props shape
-
- Props shape
- <*Element> components
- Available components
- Props shape
- Using onReady
- injectStripe HOC
- Example
- Troubleshooting
- Development
The fastest way to start playing around with react-stripe-elements is with
this JSFiddle:
You can also play around with the demo locally. The source code is in
demo/. To run it:
``shell
git clone https://github.com/stripe/react-stripe-elements
cd react-stripe-elements
yarn install
yarn run demo
`
Now go to
> :warning: PaymentRequestButtonElement will not render unless the page isPaymentRequestButtonElement
> served over HTTPS. To demo , you can tunnel over
> HTTPS to the local server using ngrok or a similar service.
!Screenshot of the demo running
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);
`html`
`html`
In order for your application to have access to
the Stripe object,
let's add StripeProvider to our root React App component:
`jsx
// index.js
import React from 'react';
import {render} from 'react-dom';
import {StripeProvider} from 'react-stripe-elements';
import MyStoreCheckout from './MyStoreCheckout';
const App = () => {
return (
);
};
render(
`
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.
`jsx
// MyStoreCheckout.js
import React from 'react';
import {Elements} from 'react-stripe-elements';
import InjectedCheckoutForm from './CheckoutForm';
class MyStoreCheckout extends React.Component {
render() {
return (
);
}
}
export default MyStoreCheckout;
`
Use the injectStripe [Higher-Order Component][hoc] (HOC) to build your paymentElements
form components in the tree. The [Higher-Order Component][hoc]injectStripe
pattern in React can be unfamiliar to those who've never seen it before, so
consider reading up before continuing. The HOC provides thethis.props.stripe and this.props.elements properties that manage yourElements groups. Within an injected component, you can call any of the methods
on the [Stripe][stripe] or [Elements][elements] objects.
[hoc]: https://facebook.github.io/react/docs/higher-order-components.html
[stripe]: https://stripe.com/docs/stripe-js/reference#the-stripe-object
[elements]: https://stripe.com/docs/stripe-js/reference#the-elements-object
> :warning: NOTE injectStripe cannot be used on the same element that rendersElements
> the component; it must be used on the child component ofElements
> . injectStripe _returns a wrapped component_ that needs to sit
> under but above any code where you'd like to accessthis.props.stripe
> .
`jsx
// 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
// 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 (
export default injectStripe(CheckoutForm);
`
Now, you can use individual *Element components, such as CardElement, to
build your form.
`jsx
// CardSection.js
import React from 'react';
import {CardElement} from 'react-stripe-elements';
class CardSection extends React.Component {
render() {
return (
);
}
}
export default CardSection;
`
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 aPaymentRequest object.PaymentRequestButtonElement
You can then conditionally render the based on thepaymentRequest.canMakePayment
result of and pass the PaymentRequest Object
as a prop.
`jsx
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 ? (
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);
`
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-elements uses under the hood.
When all of these assumptions are true, you can pass the apiKey prop to 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 directly. The stripe prop can be either null or theStripe(apiKey, options)
result of using to construct a [Stripe instance].
[stripe-function]: https://stripe.com/docs/stripe-js/reference#stripe-function
We'll now cover a couple of use cases which break at least one of the
assumptions listed above.
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
`
Initialize this.state.stripe to null in the constructor, then update it incomponentDidMount when the script tag has loaded.
`jsx`
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 (
);
}
}
When loading Stripe.js asynchronously, the stripe prop provided byinjectStripe will initially be null, and will update to the Stripe instanceStripeProvider
once you pass it in to your . You can find a working demo of
this strategy in async.js. If you run the demo locally,
you can view it at
For alternatives to calling setStatein componentDidMount, consider using asetTimeout(), moving the if/else statement to the constructor, orcomponentDidMount
dynamically injecting a script tag in . For more information,
see [stripe/react-stripe-elements][issue-154].
[issue-154]: https://github.com/stripe/react-stripe-elements/issues/154
If you're using react-stripe-elements in a non-browser environmentReact.renderToString
(, etc.), Stripe.js is not available. To usereact-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 incomponentDidMount), but this time we don't have to wait for the script tag tocomponentDidMount
load in ; we can use window.Stripe directly.
`jsx`
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 (
);
}
}
Inside your form, , this.props.stripe will either benull or a valid Stripe instance. This means that it will be null when
rendered server-side, but set when rendered in a browser.
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 uses. For example, if you have a stripe
instance in a Redux store that you pass to your as a prop, you can
pass that instance directly into :
`jsx`
class App extends React.Component {
render() {
return (
);
}
}
As long as is provided a non-null stripe prop, this.props.stripeInjectedCheckoutForm
will always be available within your .
All applications using react-stripe-elements must use the react-stripe-elements
component, which sets up the Stripe context for a component tree. uses the provider pattern (which is also adopted byreact-redux
tools like andreact-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 <*Element>
component and individual components that we provide.
An integration usually wraps the 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 .
`jsx`
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 thatStripe(apiKey, options)
can be passed into . For example, if you are usingstripeAccount="acct_123"
Stripe Connect and want to act on behalf of a
connected account, you can pass as a property to. This will get used just like passing stripeAccount in theStripe
options of the constructor or like using stripe_account when your
backend calls the Stripe API directly
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 intostripe.elements(options) as props.
`jsxelements()
type ElementsProps = {
locale?: string,
fonts?: Array options is here: https://stripe.com/docs/elements/reference#elements-options`
};
These components display the UI for Elements, and must be used within
StripeProvider and Elements.
#### Available components
(More to come!)
- CardElementCardNumberElement
- CardExpiryElement
- CardCvcElement
- PaymentRequestButtonElement
- IbanElement
- IdealBankElement
-
#### Props shape
These components accept all options that can be passed intoelements.create(type, options) as props.
`jsx
type ElementProps = {
id?: string,
className?: string,
// For full documentation on the events and payloads below, see:
// https://stripe.com/docs/elements/reference#element-on
onBlur?: () => void,
onChange?: (changeObject: Object) => void,
onFocus?: () => void,
onReady?: (StripeElement) => void,
};
`
The props for the PaymentRequestButtonElement are:
`jsx
type PaymentRequestButtonProps = {
id?: string,
className?: string,
paymentRequest: StripePaymentRequest,
onBlur?: () => void,
onClick?: () => void,
onFocus?: () => void,
onReady?: (StripeElement) => void,
};
`
#### Using onReady
Note that the onReady callback gives you access to the underlying [Element]
created with Stripe.js. You can use this to get access to all the underlying
methods that a Stripe Element supports.
For example, you can use onReady to force your element to focus:
`jsx
// CardSection.js
import React from 'react';
import {CardElement} from 'react-stripe-elements';
class CardSection extends React.Component {
render = () => {
return (
);
};
}
export default CardSection;
`
(Note that this functionality is new as of react-stripe-elements v1.6.0.)
[element]: https://stripe.com/docs/stripe-js/reference#other-methods
`jsx`
function injectStripe(
WrappedComponent: ReactClass,
options?: {
withRef?: boolean = false,
}
): ReactClass;
Use injectStripe to wrap a component that needs to interact with Stripe.js
to create sources or tokens.
1. First, create a component that accepts the stripe prop and calls one ofinjectStripe
the Stripe or Elements methods when necessary.
2. Wrap that component by passing it to so that it actuallystripe
receives the and elements props.injectStripe
3. Render the component that returns.
#### Example
`jsx
// 1. Create a component that uses this.props.stripe:
class CheckoutForm extends React.Component {
render() {
/ ... /
}
onCompleteCheckout() {
this.props.stripe
.createPaymentMethod({
type: 'card',
card: this.props.stripe.getElement('card'),
})
.then(/ ... /);
}
}
// 2. Wrap it in a higher-order component that provides the stripe prop:
const InjectedCheckoutForm = injectStripe(CheckoutForm);
// 3. Render the wrapped component in your app:
const CheckoutRoute = (props) => (
injectStripe will work with any method of providing the actual Stripe instance
with StripeProvider, whether you just give it an api key,
load Stripe.js asynchronously, or
pass in an existing instance.Within the context of
Elements, stripe.createToken and stripe.createSource
wrap methods of the same name in
Stripe.js.
Calls to them automatically infer and pass the Element object as the first
argument.If the
withRef option is set to true, the wrapped component instance will be
available with the getWrappedInstance() method of the wrapper component. This
feature can not be used if the wrapped component is a stateless function
component.Within the wrapped component, the
stripe and elements props have the type:`jsx
type FactoryProps = {
elements: null | {
getElement: (type: string) => Element | null,
// For more detail and documentation on other methods available on
// the elements object, please refer to our official documentation:
// https://stripe.com/docs/elements/reference#the-elements-object
},
stripe: null | {
createToken: (tokenData: {type?: string}) => Promise<{
token?: Object,
error?: Object,
}>,
createSource: (sourceData: {type: string}) => Promise<{
source?: Object,
error?: Object,
}>,
createPaymentMethod: (
paymentMethodData: Object
) => Promise<{
paymentMethod?: Object,
error?: Object,
}>,
confirmCardPayment: (
clientSecret: string,
paymentIntentData?: Object
) => Promise<{
paymentIntent?: Object,
error?: Object,
}>,
confirmCardSetup: (
clientSecret: string,
paymentIntentData?: Object
) => Promise<{
setupIntent?: Object,
error?: Object,
}>,
// For more detail and documentation on other methods available on
// the stripe object, please refer to our official documentation:
// https://stripe.com/docs/elements/reference#the-stripe-object
},
};
`The
stripe and elements props can only be null if you are using one of the
Advanced integrations mentioned above, like loading
Stripe.js asynchronously or providing an existing instance. If you are using a
basic integration where you pass in an api key to , they will
always be present.Troubleshooting
react-stripe-elements may not work properly when used with components that
implement shouldComponentUpdate. react-stripe-elements relies heavily on
React's context feature and shouldComponentUpdate does not provide a way to
take context updates into account when deciding whether to allow a re-render.
These components can block context updates from reaching react-stripe-element
components in the tree.For example, when using
react-stripe-elements together with
react-redux doing the following will
not work:`jsx
const Component = connect()(injectStripe(_Component));
`In this case, the context updates originating from the
StripeProvider are not
reaching the components wrapped inside the connect function. Therefore,
react-stripe-elements components deeper in the tree break. The reason is that
the connect function of react-redux
implements shouldComponentUpdate
and blocks re-renders that are triggered by context changes outside of the
connected component.There are two ways to prevent this issue:
1. Change the order of the functions to have
injectStripe be the outermost
one:
`jsx
const Component = injectStripe(connect()(_CardForm));
`This works, because
injectStripe does not implement shouldComponentUpdate
itself, so context updates originating from the redux Provider will still
reach all components.2. You can use the [
pure: false][pure-false] option for redux-connect:
`jsx
const Component = connect(
mapStateToProps,
mapDispatchToProps,
mergeProps,
{
pure: false,
}
)(injectStripe(_CardForm));
``[pure-false]:
https://github.com/reactjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options
Install dependencies:
yarn install
Run the demo:
yarn run demo
Run the tests:
yarn run test
Build:
yarn run build
We use prettier for code formatting:
yarn run prettier
To update the ToC in the README if any of the headers changed:
yarn run doctoc
Checks:
yarn test
yarn run lint
yarn run flow