0
# Checkout Flow Components
1
2
Specialized components and providers for optimized checkout experiences. These components are available from the `/checkout` entry point and provide enhanced functionality for checkout-specific workflows.
3
4
## Import Path
5
6
```typescript
7
import {
8
CheckoutProvider,
9
useCheckout,
10
BillingAddressElement,
11
ShippingAddressElement,
12
CurrencySelectorElement,
13
PaymentElement,
14
ExpressCheckoutElement,
15
TaxIdElement
16
} from "@stripe/react-stripe-js/checkout";
17
```
18
19
## Capabilities
20
21
### CheckoutProvider
22
23
Specialized context provider for checkout flows that extends Elements functionality with checkout-specific state management.
24
25
```typescript { .api }
26
/**
27
* React context provider for checkout flows
28
* @param props - Checkout provider configuration props
29
* @returns JSX element wrapping child components with checkout context
30
*/
31
function CheckoutProvider(props: CheckoutProviderProps): JSX.Element;
32
33
interface CheckoutProviderProps {
34
/** Stripe instance or Promise resolving to Stripe instance */
35
stripe: PromiseLike<Stripe | null> | Stripe | null;
36
/** Checkout configuration options - REQUIRED */
37
options: StripeCheckoutOptions;
38
/** Child components that will have access to checkout context */
39
children: ReactNode;
40
}
41
```
42
43
### useCheckout Hook
44
45
React hook for accessing checkout state and functionality within checkout flows.
46
47
```typescript { .api }
48
/**
49
* Hook to access checkout state from CheckoutProvider context
50
* @returns Current checkout state
51
*/
52
function useCheckout(): CheckoutState;
53
54
type CheckoutState =
55
| {type: 'loading'}
56
| {type: 'success'; checkout: CheckoutValue}
57
| {type: 'error'; error: {message: string}};
58
59
type CheckoutValue = StripeCheckoutActions & StripeCheckoutSession;
60
61
interface StripeCheckoutActions {
62
/** Confirm the checkout payment */
63
confirm(): Promise<{error?: StripeError}>;
64
/** Cancel the checkout session */
65
cancel(): void;
66
/** Redirect to the checkout URL */
67
redirect(): void;
68
}
69
```
70
71
**Usage Examples:**
72
73
```typescript
74
import React from 'react';
75
import { CheckoutProvider, useCheckout } from '@stripe/react-stripe-js/checkout';
76
import { loadStripe } from '@stripe/stripe-js';
77
78
const stripePromise = loadStripe('pk_test_...');
79
80
const CheckoutStatus = () => {
81
const checkoutState = useCheckout();
82
83
switch (checkoutState.type) {
84
case 'loading':
85
return <div>Loading checkout...</div>;
86
87
case 'success':
88
return (
89
<div className="checkout-success">
90
<h2>Checkout Ready</h2>
91
<button onClick={() => checkoutState.checkout.confirm()}>
92
Confirm Payment
93
</button>
94
<button onClick={() => checkoutState.checkout.cancel()}>
95
Cancel
96
</button>
97
</div>
98
);
99
100
case 'error':
101
return (
102
<div className="checkout-error">
103
<h2>Checkout Error</h2>
104
<p>{checkoutState.error.message}</p>
105
</div>
106
);
107
108
default:
109
return null;
110
}
111
};
112
113
const CheckoutFlow = ({ checkoutSessionId }) => {
114
return (
115
<CheckoutProvider stripe={stripePromise}>
116
<div className="checkout-container">
117
<h1>Complete Your Purchase</h1>
118
<CheckoutStatus />
119
</div>
120
</CheckoutProvider>
121
);
122
};
123
```
124
125
### BillingAddressElement
126
127
Specialized address element optimized for billing address collection in checkout flows.
128
129
```typescript { .api }
130
/**
131
* Billing address element for checkout flows
132
* @param props - Billing address element configuration props
133
* @returns JSX element for billing address collection
134
*/
135
function BillingAddressElement(props: BillingAddressElementProps): JSX.Element;
136
137
interface BillingAddressElementProps extends ElementProps {
138
/** Configuration options for billing address */
139
options?: StripeCheckoutAddressElementOptions;
140
/** Triggered when the Element is fully rendered */
141
onReady?: (element: StripeAddressElement) => any;
142
/** Triggered when the escape key is pressed */
143
onEscape?: () => any;
144
/** Triggered when the Element fails to load */
145
onLoadError?: (event: {elementType: 'address'; error: StripeError}) => any;
146
/** Triggered when the loader UI is mounted */
147
onLoaderStart?: (event: {elementType: 'address'}) => any;
148
}
149
150
interface StripeCheckoutAddressElementOptions {
151
/** Fields to collect */
152
fields?: {
153
phone?: 'auto' | 'always' | 'never';
154
};
155
/** Address validation options */
156
validation?: {
157
mode?: 'auto' | 'always' | 'never';
158
};
159
/** Default values */
160
defaultValues?: {
161
name?: string;
162
address?: {
163
line1?: string;
164
line2?: string;
165
city?: string;
166
state?: string;
167
postal_code?: string;
168
country?: string;
169
};
170
phone?: string;
171
};
172
}
173
```
174
175
### ShippingAddressElement
176
177
Specialized address element optimized for shipping address collection in checkout flows.
178
179
```typescript { .api }
180
/**
181
* Shipping address element for checkout flows
182
* @param props - Shipping address element configuration props
183
* @returns JSX element for shipping address collection
184
*/
185
function ShippingAddressElement(props: ShippingAddressElementProps): JSX.Element;
186
187
interface ShippingAddressElementProps extends ElementProps {
188
/** Configuration options for shipping address */
189
options?: StripeCheckoutAddressElementOptions;
190
/** Triggered when the Element is fully rendered */
191
onReady?: (element: StripeAddressElement) => any;
192
/** Triggered when the escape key is pressed */
193
onEscape?: () => any;
194
/** Triggered when the Element fails to load */
195
onLoadError?: (event: {elementType: 'address'; error: StripeError}) => any;
196
/** Triggered when the loader UI is mounted */
197
onLoaderStart?: (event: {elementType: 'address'}) => any;
198
}
199
```
200
201
**Address Elements Usage Example:**
202
203
```typescript
204
import React, { useState } from 'react';
205
import {
206
CheckoutProvider,
207
BillingAddressElement,
208
ShippingAddressElement,
209
PaymentElement
210
} from '@stripe/react-stripe-js/checkout';
211
212
const CheckoutForm = ({ stripePromise }) => {
213
const [billingAddress, setBillingAddress] = useState(null);
214
const [shippingAddress, setShippingAddress] = useState(null);
215
const [sameAsShipping, setSameAsShipping] = useState(false);
216
217
const handleBillingChange = (event) => {
218
if (event.complete) {
219
setBillingAddress(event.value);
220
}
221
};
222
223
const handleShippingChange = (event) => {
224
if (event.complete) {
225
setShippingAddress(event.value);
226
if (sameAsShipping) {
227
setBillingAddress(event.value);
228
}
229
}
230
};
231
232
return (
233
<CheckoutProvider stripe={stripePromise}>
234
<form className="checkout-form">
235
<div className="address-section">
236
<h3>Shipping Address</h3>
237
<ShippingAddressElement
238
options={{
239
fields: {
240
phone: 'always'
241
},
242
validation: {
243
mode: 'auto'
244
}
245
}}
246
onChange={handleShippingChange}
247
/>
248
</div>
249
250
<div className="billing-section">
251
<label>
252
<input
253
type="checkbox"
254
checked={sameAsShipping}
255
onChange={(e) => setSameAsShipping(e.target.checked)}
256
/>
257
Same as shipping address
258
</label>
259
260
{!sameAsShipping && (
261
<>
262
<h3>Billing Address</h3>
263
<BillingAddressElement
264
options={{
265
fields: {
266
phone: 'never'
267
}
268
}}
269
onChange={handleBillingChange}
270
/>
271
</>
272
)}
273
</div>
274
275
<div className="payment-section">
276
<h3>Payment Information</h3>
277
<PaymentElement />
278
</div>
279
280
<button
281
type="submit"
282
disabled={!billingAddress || !shippingAddress}
283
>
284
Complete Purchase
285
</button>
286
</form>
287
</CheckoutProvider>
288
);
289
};
290
```
291
292
### CurrencySelectorElement
293
294
Currency selection element for international checkout flows (requires beta access).
295
296
```typescript { .api }
297
/**
298
* Currency selector element for international checkouts
299
* Requires beta access - contact Stripe support for more information
300
* @param props - Currency selector element configuration props
301
* @returns JSX element for currency selection
302
*/
303
function CurrencySelectorElement(props: CurrencySelectorElementProps): JSX.Element;
304
305
interface CurrencySelectorElementProps extends ElementProps {
306
/** Triggered when the Element is fully rendered */
307
onReady?: (element: StripeCurrencySelectorElement) => any;
308
/** Triggered when the escape key is pressed */
309
onEscape?: () => any;
310
/** Triggered when the Element fails to load */
311
onLoadError?: (event: {elementType: 'currencySelector'; error: StripeError}) => any;
312
/** Triggered when the loader UI is mounted */
313
onLoaderStart?: (event: {elementType: 'currencySelector'}) => any;
314
}
315
```
316
317
### Checkout-Optimized PaymentElement
318
319
Specialized PaymentElement optimized for checkout flows with enhanced options.
320
321
```typescript { .api }
322
/**
323
* Payment element optimized for checkout flows
324
* @param props - Checkout payment element configuration props
325
* @returns JSX element for payment method collection
326
*/
327
function PaymentElement(props: CheckoutPaymentElementProps): JSX.Element;
328
329
type CheckoutPaymentElementProps = Omit<PaymentElementProps, 'options'> & {
330
/** Checkout-specific payment element options */
331
options?: StripeCheckoutPaymentElementOptions;
332
};
333
334
interface StripeCheckoutPaymentElementOptions extends StripePaymentElementOptions {
335
/** Enhanced layout options for checkout */
336
layout?: {
337
type?: 'tabs' | 'accordion' | 'auto';
338
defaultCollapsed?: boolean;
339
radios?: boolean;
340
spacedAccordionItems?: boolean;
341
};
342
/** Checkout-specific payment method configuration */
343
paymentMethodOrder?: string[];
344
}
345
```
346
347
### Checkout-Optimized ExpressCheckoutElement
348
349
Express checkout element optimized for checkout flows.
350
351
```typescript { .api }
352
/**
353
* Express checkout element optimized for checkout flows
354
* @param props - Checkout express checkout element configuration props
355
* @returns JSX element for express payment methods
356
*/
357
function ExpressCheckoutElement(props: CheckoutExpressCheckoutElementProps): JSX.Element;
358
359
type CheckoutExpressCheckoutElementProps = Omit<
360
ExpressCheckoutElementProps,
361
'options' | 'onClick' | 'onCancel' | 'onShippingAddressChange' | 'onShippingRateChange'
362
> & {
363
/** Checkout-specific express checkout options */
364
options?: StripeCheckoutExpressCheckoutElementOptions;
365
};
366
367
interface StripeCheckoutExpressCheckoutElementOptions {
368
/** Payment method types to enable */
369
paymentMethods?: {
370
applePay?: 'auto' | 'always' | 'never';
371
googlePay?: 'auto' | 'always' | 'never';
372
link?: 'auto' | 'always' | 'never';
373
};
374
/** Button theme customization */
375
buttonTheme?: {
376
applePay?: 'black' | 'white' | 'white-outline';
377
googlePay?: 'black' | 'white';
378
};
379
/** Layout configuration for checkout */
380
layout?: {
381
maxColumns?: number;
382
maxRows?: number;
383
};
384
}
385
```
386
387
### Checkout-Optimized TaxIdElement
388
389
Tax ID element optimized for business checkout flows.
390
391
```typescript { .api }
392
/**
393
* Tax ID element optimized for checkout flows
394
* @param props - Checkout tax ID element configuration props
395
* @returns JSX element for tax ID collection
396
*/
397
function TaxIdElement(props: CheckoutTaxIdElementProps): JSX.Element;
398
399
interface CheckoutTaxIdElementProps extends TaxIdElementProps {
400
/** Checkout-specific tax ID options */
401
options: StripeCheckoutTaxIdElementOptions;
402
}
403
404
interface StripeCheckoutTaxIdElementOptions extends StripeTaxIdElementOptions {
405
/** Required for checkout flows */
406
required?: boolean;
407
/** Checkout-specific tax ID types */
408
supportedTypes?: Array<{
409
type: string;
410
country: string;
411
required?: boolean;
412
}>;
413
}
414
```
415
416
**Complete Checkout Flow Example:**
417
418
```typescript
419
import React, { useState } from 'react';
420
import {
421
CheckoutProvider,
422
useCheckout,
423
BillingAddressElement,
424
ShippingAddressElement,
425
PaymentElement,
426
ExpressCheckoutElement,
427
CurrencySelectorElement,
428
TaxIdElement
429
} from '@stripe/react-stripe-js/checkout';
430
import { loadStripe } from '@stripe/stripe-js';
431
432
const stripePromise = loadStripe('pk_test_...');
433
434
const FullCheckoutFlow = () => {
435
const [step, setStep] = useState('shipping');
436
const [addresses, setAddresses] = useState({
437
shipping: null,
438
billing: null
439
});
440
const [businessCheckout, setBusinessCheckout] = useState(false);
441
442
const CheckoutSteps = () => {
443
const checkoutState = useCheckout();
444
445
const handleShippingComplete = (address) => {
446
setAddresses(prev => ({ ...prev, shipping: address }));
447
setStep('billing');
448
};
449
450
const handleBillingComplete = (address) => {
451
setAddresses(prev => ({ ...prev, billing: address }));
452
setStep('payment');
453
};
454
455
const handlePaymentSubmit = async () => {
456
if (checkoutState.type === 'success') {
457
try {
458
const result = await checkoutState.checkout.confirm();
459
if (result.error) {
460
console.error('Payment failed:', result.error);
461
} else {
462
setStep('complete');
463
}
464
} catch (error) {
465
console.error('Checkout error:', error);
466
}
467
}
468
};
469
470
return (
471
<div className="checkout-steps">
472
{step === 'shipping' && (
473
<div className="step">
474
<h2>Shipping Information</h2>
475
<ShippingAddressElement
476
options={{
477
fields: { phone: 'always' },
478
validation: { mode: 'auto' }
479
}}
480
onChange={(event) => {
481
if (event.complete) {
482
handleShippingComplete(event.value);
483
}
484
}}
485
/>
486
</div>
487
)}
488
489
{step === 'billing' && (
490
<div className="step">
491
<h2>Billing Information</h2>
492
493
<label>
494
<input
495
type="checkbox"
496
checked={businessCheckout}
497
onChange={(e) => setBusinessCheckout(e.target.checked)}
498
/>
499
This is a business purchase
500
</label>
501
502
<BillingAddressElement
503
options={{
504
fields: { phone: 'never' },
505
defaultValues: addresses.shipping
506
}}
507
onChange={(event) => {
508
if (event.complete) {
509
handleBillingComplete(event.value);
510
}
511
}}
512
/>
513
514
{businessCheckout && (
515
<div className="business-info">
516
<h3>Business Information</h3>
517
<TaxIdElement
518
options={{
519
required: true,
520
supportedTypes: [
521
{ type: 'us_ein', country: 'US', required: true },
522
{ type: 'eu_vat', country: 'DE' }
523
]
524
}}
525
/>
526
</div>
527
)}
528
</div>
529
)}
530
531
{step === 'payment' && (
532
<div className="step">
533
<h2>Payment Method</h2>
534
535
<div className="express-checkout">
536
<ExpressCheckoutElement
537
options={{
538
paymentMethods: {
539
applePay: 'auto',
540
googlePay: 'auto',
541
link: 'auto'
542
},
543
buttonTheme: {
544
applePay: 'black',
545
googlePay: 'black'
546
}
547
}}
548
/>
549
550
<div className="divider">or</div>
551
</div>
552
553
<PaymentElement
554
options={{
555
layout: {
556
type: 'tabs',
557
defaultCollapsed: false
558
},
559
paymentMethodOrder: ['card', 'klarna', 'afterpay_clearpay']
560
}}
561
/>
562
563
<button
564
onClick={handlePaymentSubmit}
565
disabled={checkoutState.type !== 'success'}
566
className="submit-payment"
567
>
568
Complete Purchase
569
</button>
570
</div>
571
)}
572
573
{step === 'complete' && (
574
<div className="step">
575
<h2>Order Complete!</h2>
576
<p>Thank you for your purchase.</p>
577
</div>
578
)}
579
</div>
580
);
581
};
582
583
return (
584
<CheckoutProvider stripe={stripePromise}>
585
<div className="checkout-container">
586
<div className="checkout-progress">
587
<div className={`step ${step === 'shipping' ? 'active' : ''}`}>
588
Shipping
589
</div>
590
<div className={`step ${step === 'billing' ? 'active' : ''}`}>
591
Billing
592
</div>
593
<div className={`step ${step === 'payment' ? 'active' : ''}`}>
594
Payment
595
</div>
596
</div>
597
598
<CheckoutSteps />
599
</div>
600
</CheckoutProvider>
601
);
602
};
603
604
export default FullCheckoutFlow;
605
```
606
607
## Error Handling in Checkout Flows
608
609
```typescript
610
const CheckoutWithErrorHandling = () => {
611
const [errors, setErrors] = useState({});
612
613
const handleElementError = (elementType) => (event) => {
614
if (event.error) {
615
setErrors(prev => ({
616
...prev,
617
[elementType]: event.error.message
618
}));
619
} else {
620
setErrors(prev => {
621
const newErrors = { ...prev };
622
delete newErrors[elementType];
623
return newErrors;
624
});
625
}
626
};
627
628
const hasErrors = Object.keys(errors).length > 0;
629
630
return (
631
<CheckoutProvider stripe={stripePromise}>
632
<div className="checkout-with-errors">
633
{hasErrors && (
634
<div className="error-summary">
635
<h3>Please fix the following errors:</h3>
636
<ul>
637
{Object.entries(errors).map(([element, error]) => (
638
<li key={element}>
639
<strong>{element}:</strong> {error}
640
</li>
641
))}
642
</ul>
643
</div>
644
)}
645
646
<ShippingAddressElement
647
onChange={handleElementError('shipping')}
648
onLoadError={handleElementError('shipping')}
649
/>
650
651
<BillingAddressElement
652
onChange={handleElementError('billing')}
653
onLoadError={handleElementError('billing')}
654
/>
655
656
<PaymentElement
657
onChange={handleElementError('payment')}
658
onLoadError={handleElementError('payment')}
659
/>
660
661
<button disabled={hasErrors}>
662
Complete Purchase
663
</button>
664
</div>
665
</CheckoutProvider>
666
);
667
};
668
```