Skip to content

Commit 85cccb7

Browse files
Support React StrictMode (#292)
1 parent 9ca6803 commit 85cccb7

14 files changed

+2487
-2280
lines changed

.storybook/example.stories.js

-6
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,11 @@ import {storiesOf, module} from '@storybook/react';
44
import React, {useEffect, useState} from 'react';
55

66
const ExampleComponent = ({file}) => {
7-
// force iframe to reload on each example
8-
if (window.reload) {
9-
window.location.href = window.location.href;
10-
}
11-
127
const [example, setExample] = useState(null);
138

149
useEffect(() => {
1510
import(`../examples/${file}`).then(({default: Example}) => {
1611
setExample(<Example />);
17-
window.reload = true;
1812
});
1913
}, []);
2014

.storybook/main.js

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
module.exports = {
22
stories: ['./example.stories.js'],
3+
reactOptions: {
4+
strictMode: true,
5+
},
36
};

README.md

-3
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@ React components for
88

99
## Requirements
1010

11-
We don't currently support React 18, but plan to
12-
([#273](https://github.com/stripe/react-stripe-js/issues/273)).
13-
1411
The minimum supported version of React is v16.8. If you use an older version,
1512
upgrade React to use this library. If you prefer not to upgrade your React
1613
version, we recommend using legacy

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

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import React from 'react';
66
import {loadStripe} from '@stripe/stripe-js';
77
import {CardElement, Elements, ElementsConsumer} from '../../src';
8+
9+
import '../styles/common.css';
810
import '../styles/2-Card-Detailed.css';
911

1012
const CARD_OPTIONS = {

examples/hooks/1-Card-Detailed.js

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import React, {useState} from 'react';
66
import {loadStripe} from '@stripe/stripe-js';
77
import {CardElement, Elements, useElements, useStripe} from '../../src';
8+
9+
import '../styles/common.css';
810
import '../styles/2-Card-Detailed.css';
911

1012
const CARD_OPTIONS = {

examples/hooks/9-Payment-Element.js

+129
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
// This example shows you how to set up React Stripe.js and use Elements.
2+
// Learn how to accept a payment using the official Stripe docs.
3+
// https://stripe.com/docs/payments/accept-a-payment#web
4+
5+
import React from 'react';
6+
import {loadStripe} from '@stripe/stripe-js';
7+
import {PaymentElement, Elements, useElements, useStripe} from '../../src';
8+
9+
import '../styles/common.css';
10+
11+
const CheckoutForm = () => {
12+
const [status, setStatus] = React.useState();
13+
const [loading, setLoading] = React.useState(false);
14+
const stripe = useStripe();
15+
const elements = useElements();
16+
17+
const handleSubmit = async (event) => {
18+
// Block native form submission.
19+
event.preventDefault();
20+
21+
if (!stripe || !elements) {
22+
// Stripe.js has not loaded yet. Make sure to disable
23+
// form submission until Stripe.js has loaded.
24+
return;
25+
}
26+
27+
setLoading(true);
28+
29+
stripe
30+
.confirmPayment({
31+
elements,
32+
redirect: 'if_required',
33+
confirmParams: {return_url: window.location.href},
34+
})
35+
.then((res) => {
36+
setLoading(false);
37+
if (res.error) {
38+
console.error(res.error);
39+
setStatus(res.error.message);
40+
} else {
41+
setStatus(res.paymentIntent.status);
42+
}
43+
});
44+
};
45+
46+
return (
47+
<form onSubmit={handleSubmit}>
48+
<PaymentElement />
49+
<button type="submit" disabled={!stripe || loading}>
50+
{loading ? 'Processing...' : 'Pay'}
51+
</button>
52+
{status && <p>{status}</p>}
53+
</form>
54+
);
55+
};
56+
57+
const THEMES = ['stripe', 'flat', 'none'];
58+
59+
const App = () => {
60+
const [pk, setPK] = React.useState(
61+
window.sessionStorage.getItem('react-stripe-js-pk') || ''
62+
);
63+
const [clientSecret, setClientSecret] = React.useState('');
64+
65+
React.useEffect(() => {
66+
window.sessionStorage.setItem('react-stripe-js-pk', pk || '');
67+
}, [pk]);
68+
69+
const [stripePromise, setStripePromise] = React.useState();
70+
const [theme, setTheme] = React.useState('stripe');
71+
72+
const handleSubmit = (e) => {
73+
e.preventDefault();
74+
setStripePromise(loadStripe(pk));
75+
};
76+
77+
const handleThemeChange = (e) => {
78+
setTheme(e.target.value);
79+
};
80+
81+
const handleUnload = () => {
82+
setStripePromise(null);
83+
setClientSecret(null);
84+
};
85+
86+
return (
87+
<>
88+
<form onSubmit={handleSubmit}>
89+
<label>
90+
Intent client_secret
91+
<input
92+
value={clientSecret}
93+
onChange={(e) => setClientSecret(e.target.value)}
94+
/>
95+
</label>
96+
<label>
97+
Publishable key{' '}
98+
<input value={pk} onChange={(e) => setPK(e.target.value)} />
99+
</label>
100+
<button style={{marginRight: 10}} type="submit">
101+
Load
102+
</button>
103+
<button type="button" onClick={handleUnload}>
104+
Unload
105+
</button>
106+
<label>
107+
Theme
108+
<select onChange={handleThemeChange}>
109+
{THEMES.map((val) => (
110+
<option key={val} value={val}>
111+
{val}
112+
</option>
113+
))}
114+
</select>
115+
</label>
116+
</form>
117+
{stripePromise && clientSecret && (
118+
<Elements
119+
stripe={stripePromise}
120+
options={{clientSecret, appearance: {theme}}}
121+
>
122+
<CheckoutForm />
123+
</Elements>
124+
)}
125+
</>
126+
);
127+
};
128+
129+
export default App;

examples/styles/2-Card-Detailed.css

+28-45
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,16 @@
22
box-sizing: border-box;
33
}
44

5-
input,
6-
button {
5+
.AppWrapper input,
6+
.AppWrapper button {
7+
all: unset;
78
-webkit-appearance: none;
89
-moz-appearance: none;
910
appearance: none;
1011
outline: none;
1112
border-style: none;
1213
}
1314

14-
html {
15-
background-color: #6772e5;
16-
font-size: 16px;
17-
font-family: Roboto, Open Sans, Segoe UI, sans-serif;
18-
font-weight: 500;
19-
font-style: normal;
20-
text-rendering: optimizeLegibility;
21-
height: 100%;
22-
}
23-
24-
body {
25-
height: 100%;
26-
margin: 0;
27-
}
28-
29-
#root {
30-
height: 100%;
31-
display: flex;
32-
align-items: center;
33-
justify-content: center;
34-
}
35-
3615
.AppWrapper {
3716
width: 500px;
3817
height: 400px;
@@ -50,11 +29,11 @@ body {
5029
}
5130
}
5231

53-
.Form {
32+
.AppWrapper .Form {
5433
animation: fade 200ms ease-out;
5534
}
5635

57-
.FormGroup {
36+
.AppWrapper .FormGroup {
5837
margin: 0 15px 20px;
5938
padding: 0;
6039
border-style: none;
@@ -65,7 +44,7 @@ body {
6544
border-radius: 4px;
6645
}
6746

68-
.FormRow {
47+
.AppWrapper .FormRow {
6948
display: -ms-flexbox;
7049
display: flex;
7150
-ms-flex-align: center;
@@ -74,11 +53,12 @@ body {
7453
border-top: 1px solid #819efc;
7554
}
7655

77-
.FormRow:first-child {
56+
.AppWrapper .FormRow:first-child {
7857
border-top: none;
7958
}
8059

81-
.FormRowLabel {
60+
.AppWrapper .FormRowLabel {
61+
all: unset;
8262
width: 15%;
8363
min-width: 70px;
8464
padding: 11px 0;
@@ -94,14 +74,14 @@ body {
9474
opacity: 1;
9575
}
9676
}
97-
.FormRowInput:-webkit-autofill {
77+
.AppWrapper .FormRowInput:-webkit-autofill {
9878
-webkit-text-fill-color: #fce883;
9979
/* Hack to hide the default webkit autofill */
10080
transition: background-color 100000000s;
10181
animation: 1ms void-animation-out;
10282
}
10383

104-
.FormRowInput {
84+
.AppWrapper .FormRowInput {
10585
font-size: 16px;
10686
width: 100%;
10787
padding: 11px 15px 11px 0;
@@ -110,20 +90,23 @@ body {
11090
animation: 1ms void-animation-out;
11191
}
11292

113-
.FormRowInput::placeholder {
93+
.AppWrapper .FormRowInput::placeholder {
11494
color: #87bbfd;
11595
}
11696

117-
.StripeElement--webkit-autofill {
97+
.AppWrapper .StripeElement--webkit-autofill {
11898
background: transparent !important;
11999
}
120100

121-
.StripeElement {
101+
.AppWrapper .StripeElement {
122102
width: 100%;
123103
padding: 11px 15px 11px 0;
104+
margin: 0;
105+
background: none;
124106
}
125107

126-
.SubmitButton {
108+
.AppWrapper .SubmitButton {
109+
text-align: center;
127110
display: block;
128111
font-size: 16px;
129112
width: calc(100% - 30px);
@@ -140,28 +123,28 @@ body {
140123
will-change: transform, background-color, box-shadow;
141124
}
142125

143-
.SubmitButton:active {
126+
.AppWrapper .SubmitButton:active {
144127
background-color: #d782d9;
145128
box-shadow: 0 6px 9px rgba(50, 50, 93, 0.06), 0 2px 5px rgba(0, 0, 0, 0.08),
146129
inset 0 1px 0 #e298d8;
147130
transform: scale(0.99);
148131
}
149132

150-
.SubmitButton.SubmitButton--error {
133+
.AppWrapper .SubmitButton.SubmitButton--error {
151134
transform: translateY(15px);
152135
}
153-
.SubmitButton.SubmitButton--error:active {
136+
.AppWrapper .SubmitButton.SubmitButton--error:active {
154137
transform: scale(0.99) translateY(15px);
155138
}
156139

157-
.SubmitButton:disabled {
140+
.AppWrapper .SubmitButton:disabled {
158141
opacity: 0.5;
159142
cursor: default;
160143
background-color: #7795f8;
161144
box-shadow: none;
162145
}
163146

164-
.ErrorMessage {
147+
.AppWrapper .ErrorMessage {
165148
color: #fff;
166149
position: absolute;
167150
display: flex;
@@ -178,25 +161,25 @@ body {
178161
will-change: opacity, transform;
179162
}
180163

181-
.ErrorMessage svg {
164+
.AppWrapper .ErrorMessage svg {
182165
margin-right: 10px;
183166
}
184167

185-
.Result {
168+
.AppWrapper .Result {
186169
margin-top: 50px;
187170
text-align: center;
188171
animation: fade 200ms ease-out;
189172
}
190173

191-
.ResultTitle {
174+
.AppWrapper .ResultTitle {
192175
color: #fff;
193176
font-weight: 500;
194177
margin-bottom: 8px;
195178
font-size: 17px;
196179
text-align: center;
197180
}
198181

199-
.ResultMessage {
182+
.AppWrapper .ResultMessage {
200183
color: #9cdbff;
201184
font-size: 14px;
202185
font-weight: 400;
@@ -205,7 +188,7 @@ body {
205188
text-align: center;
206189
}
207190

208-
.ResetButton {
191+
.AppWrapper .ResetButton {
209192
border: 0;
210193
cursor: pointer;
211194
background: transparent;

examples/styles/common.css

+2-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ button[disabled] {
6060
opacity: 0.6;
6161
}
6262

63-
input {
63+
input,
64+
select {
6465
display: block;
6566
border: none;
6667
font-size: 18px;

0 commit comments

Comments
 (0)