Skip to content

Commit 24c0c12

Browse files
Examples and README updates (#22)
* make readme less hooks centric * Update all examples to use loadStripe; add more class based examples * requested changes; prb fixes * pass through disabled
1 parent 9515097 commit 24c0c12

20 files changed

+1054
-309
lines changed

.storybook/example.stories.js

+1-38
Original file line numberDiff line numberDiff line change
@@ -3,47 +3,14 @@
33
import {storiesOf, module} from '@storybook/react';
44
import React, {useEffect, useState} from 'react';
55

6-
const SyncExample = ({file}) => {
6+
const ExampleComponent = ({file}) => {
77
// force iframe to reload on each example
88
if (window.reload) {
99
window.location.href = window.location.href;
1010
}
1111

1212
const [example, setExample] = useState(null);
1313

14-
// We need to dynamically load Stripe.js, since
15-
// we want to demo async loading and we don't want to
16-
// have it preloaded for those demos.
17-
//
18-
// To effectively model sync loading, we need to load the script,
19-
// and only after it has loaded we can dynamically import a
20-
// demo that assumes Stripe has been synchronously loaded.
21-
useEffect(() => {
22-
const stripeJs = document.createElement('script');
23-
stripeJs.src = 'https://js.stripe.com/v3/';
24-
stripeJs.async = true;
25-
stripeJs.onload = () => {
26-
import(`../examples/${file}`).then(({default: Example}) => {
27-
setExample(<Example />);
28-
window.reload = true;
29-
});
30-
};
31-
document.body.appendChild(stripeJs);
32-
}, []);
33-
34-
return example;
35-
};
36-
37-
const AsyncExample = ({file}) => {
38-
// force iframe to reload on each example
39-
if (window.reload) {
40-
window.location.href = window.location.href;
41-
}
42-
43-
const [example, setExample] = useState(null);
44-
45-
// For async demos, we don't need to preload Stripe before
46-
// loading the module, since this is done inside the demo.
4714
useEffect(() => {
4815
import(`../examples/${file}`).then(({default: Example}) => {
4916
setExample(<Example />);
@@ -54,17 +21,13 @@ const AsyncExample = ({file}) => {
5421
return example;
5522
};
5623

57-
const ASYNC_EXAMPLES = ['Card Async'];
58-
5924
const addDemo = (directory, file, stories) => {
6025
const name = file
6126
.replace('.js', '')
6227
.split('-')
6328
.slice(1)
6429
.join(' ');
6530

66-
const async = ASYNC_EXAMPLES.indexOf(name) !== -1;
67-
const ExampleComponent = async ? AsyncExample : SyncExample;
6831
stories.add(name, () => <ExampleComponent file={`${directory}/${file}`} />);
6932
};
7033

README.md

+71-17
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,24 @@ React components for [Stripe.js](https://stripe.com/docs/stripe-js) and
2020

2121
### Minimal Example
2222

23+
```sh
24+
npm install @stripe/react-stripe-js @stripe/stripe-js
25+
```
26+
27+
#### Using Hooks
28+
2329
```jsx
2430
import React from 'react';
2531
import ReactDOM from 'react-dom';
26-
32+
import {loadStripe} from '@stripe/react-stripe-js';
2733
import {
2834
CardElement,
2935
Elements,
3036
useStripe,
3137
useElements,
3238
} from '@stripe/react-stripe-js';
3339

34-
const stripe = window.Stripe('pk_test_6pRNASCoBOKtIshFeQd4XMUh');
35-
36-
const MyCheckoutForm = () => {
40+
const CheckoutForm = () => {
3741
const stripe = useStripe();
3842
const elements = useElements();
3943

@@ -48,29 +52,79 @@ const MyCheckoutForm = () => {
4852
return (
4953
<form onSubmit={handleSubmit}>
5054
<CardElement />
51-
<button type="submit">Pay</button>
55+
<button type="submit" disabled={!stripe}>
56+
Pay
57+
</button>
5258
</form>
5359
);
5460
};
5561

56-
const App = () => {
57-
return (
58-
<Elements stripe={stripe}>
59-
<MyCheckoutForm />
60-
</Elements>
61-
);
62-
};
62+
const stripePromise = loadStripe('pk_test_6pRNASCoBOKtIshFeQd4XMUh');
63+
64+
const App = () => (
65+
<Elements stripe={stripePromise}>
66+
<CheckoutForm />
67+
</Elements>
68+
);
69+
70+
ReactDOM.render(<App />, document.body);
71+
```
72+
73+
#### Using Class Components
74+
75+
```jsx
76+
import React from 'react';
77+
import ReactDOM from 'react-dom';
78+
import {loadStripe} from '@stripe/react-stripe-js';
79+
import {CardElement, Elements, ElementsConsumer} from '@stripe/react-stripe-js';
80+
81+
class CheckoutForm extends React.Component {
82+
handleSubmit = async (event) => {
83+
event.preventDefault();
84+
const {stripe, elements} = this.props;
85+
const {error, paymentMethod} = await stripe.createPaymentMethod({
86+
type: 'card',
87+
card: elements.getElement(CardElement),
88+
});
89+
};
90+
91+
render() {
92+
const {stripe} = this.props;
93+
return (
94+
<form onSubmit={this.handleSubmit}>
95+
<CardElement />
96+
<button type="submit" disabled={!stripe}>
97+
Pay
98+
</button>
99+
</form>
100+
);
101+
}
102+
}
103+
104+
const InjectedCheckoutForm = () => (
105+
<ElementsConsumer>
106+
{({stripe, elements}) => (
107+
<CheckoutForm stripe={stripe} elements={elements} />
108+
)}
109+
</ElementsConsumer>
110+
);
111+
112+
const stripePromise = loadStripe('pk_test_6pRNASCoBOKtIshFeQd4XMUh');
113+
114+
const App = () => (
115+
<Elements stripe={stripePromise}>
116+
<InjectedCheckoutForm />
117+
</Elements>
118+
);
63119

64120
ReactDOM.render(<App />, document.body);
65121
```
66122

67123
### Minimum Requirements
68124

69-
React Stripe.js depends on the
70-
[React Hooks API](https://reactjs.org/docs/hooks-intro.html). The minimum
71-
supported version of React is v16.8. If you use an older version, upgrade React
72-
to use this library. If you prefer not to upgrade your React version, we
73-
recommend using legacy
125+
The minimum supported version of React is v16.8. If you use an older version,
126+
upgrade React to use this library. If you prefer not to upgrade your React
127+
version, we recommend using legacy
74128
[`react-stripe-elements`](https://github.com/stripe/react-stripe-elements).
75129

76130
### Contributing

examples/.eslintrc.yml

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
extends: '../.eslintrc.yml'
3+
rules:
4+
import/no-extraneous-dependencies: 0

examples/class-components/0-Card-Minimal.js

+15-5
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
// @noflow
22

33
import React from 'react';
4+
import {loadStripe} from '@stripe/stripe-js';
45
import {CardElement, Elements, ElementsConsumer} from '../../src';
56
import '../styles/common.css';
67

7-
class MyCheckoutForm extends React.Component {
8+
class CheckoutForm extends React.Component {
89
handleSubmit = async (event) => {
910
// Block native form submission.
1011
event.preventDefault();
1112

1213
const {stripe, elements} = this.props;
1314

15+
if (!stripe || !elements) {
16+
// Stripe.js has not loaded yet. Make sure to disable
17+
// form submission until Stripe.js has loaded.
18+
return;
19+
}
20+
1421
// Get a reference to a mounted CardElement. Elements knows how
1522
// to find your CardElement because there can only ever be one of
1623
// each type of element.
@@ -29,6 +36,7 @@ class MyCheckoutForm extends React.Component {
2936
};
3037

3138
render() {
39+
const {stripe} = this.props;
3240
return (
3341
<form onSubmit={this.handleSubmit}>
3442
<CardElement
@@ -47,7 +55,9 @@ class MyCheckoutForm extends React.Component {
4755
},
4856
}}
4957
/>
50-
<button type="submit">Pay</button>
58+
<button type="submit" disabled={!stripe}>
59+
Pay
60+
</button>
5161
</form>
5262
);
5363
}
@@ -57,17 +67,17 @@ const InjectedCheckoutForm = () => {
5767
return (
5868
<ElementsConsumer>
5969
{({elements, stripe}) => (
60-
<MyCheckoutForm elements={elements} stripe={stripe} />
70+
<CheckoutForm elements={elements} stripe={stripe} />
6171
)}
6272
</ElementsConsumer>
6373
);
6474
};
6575

66-
const stripe = window.Stripe('pk_test_6pRNASCoBOKtIshFeQd4XMUh');
76+
const stripePromise = loadStripe('pk_test_6pRNASCoBOKtIshFeQd4XMUh');
6777

6878
const App = () => {
6979
return (
70-
<Elements stripe={stripe}>
80+
<Elements stripe={stripePromise}>
7181
<InjectedCheckoutForm />
7282
</Elements>
7383
);

examples/class-components/1-Card-Async.js

-98
This file was deleted.

0 commit comments

Comments
 (0)