Try Live
Add Docs
Rankings
Pricing
Enterprise
Docs
Install
Install
Docs
Pricing
Enterprise
More...
More...
Try Live
Rankings
Add Docs
React Connect.js
https://github.com/stripe/react-connect-js
Admin
React Connect.js provides React components that act as a thin wrapper around Connect.js embedded
...
Tokens:
9,759
Snippets:
39
Trust Score:
8.9
Update:
4 months ago
Context
Skills
Chat
Benchmark
78.9
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# @stripe/react-connect-js ## Introduction React Connect.js is a React wrapper library for Stripe's Connect embedded components, designed to simplify the integration of Stripe Connect functionality into React applications. This library provides a comprehensive set of React components that wrap Stripe's Connect.js SDK, enabling developers to embed payment management, account onboarding, payouts, financial accounts, issuing cards, tax management, and other Connect-related features directly into their React applications with minimal configuration. The library manages the lifecycle and state of embedded components automatically, abstracting away the complexity of direct DOM manipulation and event handling. It uses React Context to provide the ConnectInstance throughout the component tree, allowing developers to declaratively render Stripe Connect UI components with props-based configuration. The library supports all major Stripe Connect embedded components including payments, payouts, account management, onboarding, disputes, issuing cards, financial accounts, tax settings, and notification banners. ## Core Setup and Context Provider ### ConnectComponentsProvider - Root Context Provider The `ConnectComponentsProvider` wraps your application and provides the ConnectInstance context to all child components. This is required before using any Connect component. ```jsx import React from 'react'; import ReactDOM from 'react-dom'; import {loadConnectAndInitialize} from '@stripe/connect-js'; import {ConnectComponentsProvider, ConnectPayments} from '@stripe/react-connect-js'; // Fetch client secret from your backend const fetchClientSecret = async () => { const response = await fetch('/api/account_session', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({account: 'acct_1234567890'}) }); const {client_secret} = await response.json(); return client_secret; }; // Initialize Connect instance with publishable key and appearance options const connectInstance = loadConnectAndInitialize({ publishableKey: 'pk_test_51ABCDEFghijklmnop', fetchClientSecret: fetchClientSecret, appearance: { variables: { colorPrimary: '#228403', colorBackground: '#ffffff', fontFamily: 'system-ui, sans-serif' } } }); // Wrap your app with the provider const App = () => ( <ConnectComponentsProvider connectInstance={connectInstance}> <ConnectPayments /> </ConnectComponentsProvider> ); ReactDOM.render(<App />, document.getElementById('root')); ``` ## Payment Components ### ConnectPayments - Payment List Component Displays a list of payments for the connected account with filtering and pagination capabilities. ```jsx import React, {useState} from 'react'; import {ConnectPayments} from '@stripe/react-connect-js'; const PaymentsPage = () => { const [loading, setLoading] = useState(true); const [error, setError] = useState(null); return ( <div className="payments-container"> <h1>Payments</h1> {error && <div className="error">Error loading payments: {error.message}</div>} <ConnectPayments defaultFilters={{status: ['succeeded', 'pending']}} onLoaderStart={({elementTagName}) => { console.log(`${elementTagName} loading started`); setLoading(true); }} onLoadError={({error, elementTagName}) => { console.error(`${elementTagName} load error:`, error); setError(error); setLoading(false); }} /> </div> ); }; export default PaymentsPage; ``` ### ConnectPaymentDetails - Payment Detail View Shows detailed information for a specific payment, charge, or payment intent with a close callback. ```jsx import React, {useState} from 'react'; import {ConnectPaymentDetails} from '@stripe/react-connect-js'; const PaymentDetailsModal = ({paymentId, onClose}) => { return ( <div className="modal-overlay"> <div className="modal-content"> <ConnectPaymentDetails payment={paymentId} onClose={() => { console.log('Payment details closed'); onClose(); }} onLoaderStart={({elementTagName}) => { console.log('Loading payment details...'); }} onLoadError={({error}) => { console.error('Failed to load payment:', error); alert(`Error: ${error.message}`); }} /> </div> </div> ); }; // Usage example const App = () => { const [selectedPayment, setSelectedPayment] = useState(null); return ( <> <button onClick={() => setSelectedPayment('pi_3ABC123xyz')}> View Payment </button> {selectedPayment && ( <PaymentDetailsModal paymentId={selectedPayment} onClose={() => setSelectedPayment(null)} /> )} </> ); }; export default App; ``` ### ConnectPaymentDisputes - Payment Disputes Component Displays disputes associated with a specific payment, with callbacks for dispute count tracking. ```jsx import React, {useState} from 'react'; import {ConnectPaymentDisputes} from '@stripe/react-connect-js'; const PaymentDisputesPanel = ({paymentId}) => { const [disputeCount, setDisputeCount] = useState(0); return ( <div className="disputes-panel"> <h2>Disputes {disputeCount > 0 && `(${disputeCount})`}</h2> <ConnectPaymentDisputes payment={paymentId} onDisputesLoaded={({total}) => { console.log(`Loaded ${total} disputes`); setDisputeCount(total); if (total > 0) { // Send notification or analytics event window.analytics?.track('disputes_detected', {count: total}); } }} onLoaderStart={({elementTagName}) => { console.log('Loading disputes...'); }} onLoadError={({error}) => { console.error('Disputes load failed:', error); }} /> </div> ); }; export default PaymentDisputesPanel; ``` ### ConnectDisputesList - All Disputes List Shows a comprehensive list of all disputes for the connected account. ```jsx import React from 'react'; import {ConnectDisputesList} from '@stripe/react-connect-js'; const DisputesPage = () => { return ( <div className="page-container"> <header> <h1>Disputes</h1> <p>Manage and respond to payment disputes</p> </header> <ConnectDisputesList onLoaderStart={({elementTagName}) => { console.log('Loading disputes list...'); }} onLoadError={({error}) => { console.error('Failed to load disputes:', error); // Send error to monitoring service window.Sentry?.captureException(error); }} /> </div> ); }; export default DisputesPage; ``` ## Payout Components ### ConnectPayouts - Payouts Overview Displays payout summary and management interface for the connected account. ```jsx import React, {useEffect} from 'react'; import {ConnectPayouts} from '@stripe/react-connect-js'; const PayoutsPage = () => { useEffect(() => { document.title = 'Payouts - Dashboard'; }, []); return ( <div className="payouts-container"> <div className="page-header"> <h1>Payouts</h1> <p>View and manage your payouts</p> </div> <ConnectPayouts onLoaderStart={({elementTagName}) => { console.log('Payouts component loading'); }} onLoadError={({error, elementTagName}) => { console.error('Payouts failed to load:', error); alert('Unable to load payouts. Please refresh the page.'); }} /> </div> ); }; export default PayoutsPage; ``` ### ConnectPayoutsList - Detailed Payouts List Shows a comprehensive list of all payouts with filtering and sorting capabilities. ```jsx import React from 'react'; import {ConnectPayoutsList} from '@stripe/react-connect-js'; const PayoutsListPage = () => { return ( <div className="page-wrapper"> <nav className="breadcrumb"> <a href="/dashboard">Dashboard</a> / <span>Payouts</span> </nav> <ConnectPayoutsList onLoaderStart={({elementTagName}) => { console.log('Loading payouts list...'); }} onLoadError={({error}) => { console.error('Error loading payouts list:', error); }} /> </div> ); }; export default PayoutsListPage; ``` ### ConnectPayoutDetails - Payout Detail View Displays detailed information for a specific payout with a close callback. ```jsx import React, {useState} from 'react'; import {ConnectPayoutDetails} from '@stripe/react-connect-js'; const PayoutDetailsDrawer = ({payoutId, isOpen, onClose}) => { if (!isOpen) return null; return ( <div className="drawer-overlay" onClick={onClose}> <div className="drawer-content" onClick={(e) => e.stopPropagation()}> <button className="close-button" onClick={onClose}>×</button> <ConnectPayoutDetails payout={payoutId} onClose={() => { console.log(`Closed payout details for ${payoutId}`); onClose(); }} onLoaderStart={({elementTagName}) => { console.log('Loading payout details...'); }} onLoadError={({error}) => { console.error('Failed to load payout:', error); }} /> </div> </div> ); }; // Usage example const App = () => { const [drawerOpen, setDrawerOpen] = useState(false); const [selectedPayout, setSelectedPayout] = useState(null); const handleViewPayout = (payoutId) => { setSelectedPayout(payoutId); setDrawerOpen(true); }; return ( <> <button onClick={() => handleViewPayout('po_1ABC123xyz')}> View Payout Details </button> <PayoutDetailsDrawer payoutId={selectedPayout} isOpen={drawerOpen} onClose={() => setDrawerOpen(false)} /> </> ); }; export default App; ``` ### ConnectInstantPayoutsPromotion - Instant Payouts Feature Displays promotional content for instant payouts with event tracking for conversions. ```jsx import React, {useState} from 'react'; import {ConnectInstantPayoutsPromotion} from '@stripe/react-connect-js'; const InstantPayoutsPromo = () => { const [promotionVisible, setPromotionVisible] = useState(false); const [instantPayouts, setInstantPayouts] = useState([]); return ( <div className="instant-payouts-section"> {promotionVisible && ( <div className="promo-badge">New Feature Available!</div> )} <ConnectInstantPayoutsPromotion onInstantPayoutsPromotionLoaded={({promotionShown}) => { console.log(`Promotion shown: ${promotionShown}`); setPromotionVisible(promotionShown); if (promotionShown) { // Track promotion impression window.analytics?.track('instant_payouts_promo_shown'); } }} onInstantPayoutCreated={({payoutId}) => { console.log(`Instant payout created: ${payoutId}`); setInstantPayouts(prev => [...prev, payoutId]); // Track conversion window.analytics?.track('instant_payout_created', {payoutId}); alert('Instant payout created successfully!'); }} onLoaderStart={({elementTagName}) => { console.log('Loading instant payouts promotion...'); }} onLoadError={({error}) => { console.error('Promotion load error:', error); }} /> </div> ); }; export default InstantPayoutsPromo; ``` ## Account Management Components ### ConnectAccountOnboarding - Account Setup Flow Provides a complete onboarding flow for connected accounts with customizable terms of service and collection options. ```jsx import React, {useState} from 'react'; import {ConnectAccountOnboarding} from '@stripe/react-connect-js'; const OnboardingFlow = ({accountId, onComplete}) => { const [currentStep, setCurrentStep] = useState(''); const [isLoading, setIsLoading] = useState(true); return ( <div className="onboarding-container"> <div className="progress-indicator"> {isLoading ? 'Loading...' : `Current Step: ${currentStep}`} </div> <ConnectAccountOnboarding onExit={() => { console.log('Onboarding exited'); if (window.confirm('Are you sure you want to exit onboarding?')) { onComplete(false); } }} onStepChange={(stepChange) => { console.log('Step changed:', stepChange); setCurrentStep(stepChange.step || 'Unknown'); setIsLoading(false); // Track onboarding progress window.analytics?.track('onboarding_step_changed', { step: stepChange.step, accountId: accountId }); }} recipientTermsOfServiceUrl="https://example.com/recipient-tos" fullTermsOfServiceUrl="https://example.com/connect-tos" privacyPolicyUrl="https://example.com/privacy" skipTermsOfServiceCollection={false} collectionOptions={{ fields: 'eventually_due', futureRequirements: 'include' }} onLoaderStart={({elementTagName}) => { console.log('Onboarding component loading...'); setIsLoading(true); }} onLoadError={({error}) => { console.error('Onboarding load error:', error); setIsLoading(false); alert('Failed to load onboarding. Please try again.'); }} /> </div> ); }; export default OnboardingFlow; ``` ### ConnectAccountManagement - Account Settings Displays account management interface for updating connected account information. ```jsx import React from 'react'; import {ConnectAccountManagement} from '@stripe/react-connect-js'; const AccountSettingsPage = () => { return ( <div className="settings-page"> <header className="settings-header"> <h1>Account Settings</h1> <p>Update your business information and preferences</p> </header> <ConnectAccountManagement collectionOptions={{ fields: 'currently_due', futureRequirements: 'include' }} onLoaderStart={({elementTagName}) => { console.log('Loading account management...'); }} onLoadError={({error}) => { console.error('Account management load error:', error); // Send to error tracking window.Sentry?.captureException(error, { tags: {component: 'account-management'} }); }} /> </div> ); }; export default AccountSettingsPage; ``` ### ConnectNotificationBanner - Notification Display Shows important notifications and alerts for the connected account with action tracking. ```jsx import React, {useState, useEffect} from 'react'; import {ConnectNotificationBanner} from '@stripe/react-connect-js'; const NotificationSystem = () => { const [notificationCount, setNotificationCount] = useState({ total: 0, actionRequired: 0 }); useEffect(() => { // Update page title with notification count if (notificationCount.actionRequired > 0) { document.title = `(${notificationCount.actionRequired}) Notifications`; } }, [notificationCount]); return ( <div className="notification-container"> <div className="notification-header"> {notificationCount.actionRequired > 0 && ( <span className="badge urgent"> {notificationCount.actionRequired} Action Required </span> )} </div> <ConnectNotificationBanner collectionOptions={{ fields: 'eventually_due', futureRequirements: 'include' }} onNotificationsChange={({total, actionRequired}) => { console.log(`Notifications: ${total} total, ${actionRequired} require action`); setNotificationCount({total, actionRequired}); // Send notification to parent window or analytics window.parent?.postMessage({ type: 'notifications_update', data: {total, actionRequired} }, '*'); }} onLoaderStart={({elementTagName}) => { console.log('Loading notifications...'); }} onLoadError={({error}) => { console.error('Notification banner error:', error); }} /> </div> ); }; export default NotificationSystem; ``` ## Financial Components ### ConnectBalances - Account Balances Displays current balance information for the connected account across all currencies. ```jsx import React from 'react'; import {ConnectBalances} from '@stripe/react-connect-js'; const BalancesWidget = () => { return ( <div className="balances-widget"> <h2>Available Balance</h2> <ConnectBalances onLoaderStart={({elementTagName}) => { console.log('Loading balances...'); }} onLoadError={({error}) => { console.error('Balances load error:', error); // Show fallback UI or error message }} /> </div> ); }; export default BalancesWidget; ``` ### ConnectFinancialAccount - Financial Account Details Shows detailed information for a specific financial account including account and routing numbers. ```jsx import React from 'react'; import {ConnectFinancialAccount} from '@stripe/react-connect-js'; const FinancialAccountDetails = ({financialAccountId}) => { return ( <div className="financial-account-page"> <header> <h1>Financial Account</h1> <p>Account ID: {financialAccountId}</p> </header> <ConnectFinancialAccount financialAccount={financialAccountId} onLoaderStart={({elementTagName}) => { console.log('Loading financial account details...'); }} onLoadError={({error}) => { console.error('Financial account load error:', error); alert('Unable to load financial account details'); }} /> </div> ); }; // Usage example const App = () => { return ( <FinancialAccountDetails financialAccountId="fa_1ABC123xyz" /> ); }; export default App; ``` ### ConnectFinancialAccountTransactions - Transaction History Displays transaction history for a specific financial account with filtering capabilities. ```jsx import React, {useState} from 'react'; import {ConnectFinancialAccountTransactions} from '@stripe/react-connect-js'; const TransactionsPage = ({financialAccountId}) => { const [loading, setLoading] = useState(true); return ( <div className="transactions-page"> <div className="page-header"> <h1>Transactions</h1> <button disabled={loading} onClick={() => window.location.reload()}> Refresh </button> </div> <ConnectFinancialAccountTransactions financialAccount={financialAccountId} onLoaderStart={({elementTagName}) => { console.log('Loading transactions...'); setLoading(true); }} onLoadError={({error}) => { console.error('Transactions load error:', error); setLoading(false); // Show error notification window.showNotification?.('error', 'Failed to load transactions'); }} /> </div> ); }; export default TransactionsPage; ``` ## Issuing Components ### ConnectIssuingCard - Card Display Displays a virtual or physical issuing card with spend controls and card switching capabilities. ```jsx import React from 'react'; import {ConnectIssuingCard} from '@stripe/react-connect-js'; const CardDisplay = ({defaultCardId}) => { // Function to fetch ephemeral key for secure card operations const fetchEphemeralKey = async ({issuingCard, nonce}) => { const response = await fetch('/api/issuing/ephemeral-key', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({issuingCard, nonce}) }); if (!response.ok) { throw new Error('Failed to fetch ephemeral key'); } const data = await response.json(); return { issuingCard: data.issuingCard, nonce: data.nonce, ephemeralKeySecret: data.ephemeralKeySecret }; }; return ( <div className="card-display"> <h2>Your Card</h2> <ConnectIssuingCard defaultCard={defaultCardId} cardSwitching={true} showSpendControls={true} fetchEphemeralKey={fetchEphemeralKey} onLoaderStart={({elementTagName}) => { console.log('Loading card...'); }} onLoadError={({error}) => { console.error('Card load error:', error); alert('Unable to load card. Please contact support.'); }} /> </div> ); }; // Usage example const App = () => { return <CardDisplay defaultCardId="ic_1ABC123xyz" />; }; export default App; ``` ### ConnectIssuingCardsList - Multiple Cards Management Shows a list of all issuing cards with filtering by program and spend control management. ```jsx import React, {useState} from 'react'; import {ConnectIssuingCardsList} from '@stripe/react-connect-js'; const CardsManagementPage = ({issuingProgramId}) => { const [error, setError] = useState(null); const fetchEphemeralKey = async ({issuingCard, nonce}) => { try { const response = await fetch('/api/issuing/ephemeral-key', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({issuingCard, nonce}) }); const data = await response.json(); return { issuingCard: data.issuingCard, nonce: data.nonce, ephemeralKeySecret: data.ephemeralKeySecret }; } catch (err) { console.error('Ephemeral key fetch error:', err); throw err; } }; return ( <div className="cards-page"> <header> <h1>Manage Cards</h1> {error && <div className="error-banner">{error}</div>} </header> <ConnectIssuingCardsList showSpendControls={true} issuingProgram={issuingProgramId} fetchEphemeralKey={fetchEphemeralKey} onLoaderStart={({elementTagName}) => { console.log('Loading cards list...'); setError(null); }} onLoadError={({error}) => { console.error('Cards list load error:', error); setError(error.message); }} /> </div> ); }; export default CardsManagementPage; ``` ## Tax Components ### ConnectTaxRegistrations - Tax Registration Management Manages tax registrations across different countries with lifecycle event callbacks. ```jsx import React, {useState} from 'react'; import {ConnectTaxRegistrations} from '@stripe/react-connect-js'; const TaxRegistrationsPage = () => { const [registrations, setRegistrations] = useState([]); return ( <div className="tax-registrations-page"> <header> <h1>Tax Registrations</h1> <p>Manage your tax registrations across countries</p> </header> <ConnectTaxRegistrations displayCountries={['US', 'CA', 'GB', 'DE', 'FR', 'AU']} onAfterTaxRegistrationAdded={({id}) => { console.log(`Tax registration added: ${id}`); setRegistrations(prev => [...prev, id]); // Trigger backend sync fetch('/api/tax-registrations/sync', { method: 'POST', body: JSON.stringify({registrationId: id}) }); // Show success message window.showNotification?.('success', 'Tax registration added successfully'); }} onAfterTaxRegistrationExpired={({id}) => { console.log(`Tax registration expired: ${id}`); setRegistrations(prev => prev.filter(regId => regId !== id)); // Send alert email fetch('/api/notifications/tax-expiry', { method: 'POST', body: JSON.stringify({registrationId: id}) }); alert('A tax registration has expired. Please update your information.'); }} onLoaderStart={({elementTagName}) => { console.log('Loading tax registrations...'); }} onLoadError={({error}) => { console.error('Tax registrations load error:', error); }} /> </div> ); }; export default TaxRegistrationsPage; ``` ### ConnectTaxSettings - Tax Configuration Provides tax settings configuration including product tax codes and head office location. ```jsx import React, {useState} from 'react'; import {ConnectTaxSettings} from '@stripe/react-connect-js'; const TaxSettingsPage = () => { const [lastUpdated, setLastUpdated] = useState(null); return ( <div className="tax-settings-page"> <header> <h1>Tax Settings</h1> {lastUpdated && ( <p className="last-updated"> Last updated: {new Date(lastUpdated).toLocaleString()} </p> )} </header> <ConnectTaxSettings hideProductTaxCodeSelector={false} displayHeadOfficeCountries={['US', 'CA', 'GB', 'DE', 'FR', 'AU', 'JP']} onTaxSettingsUpdated={({id}) => { console.log(`Tax settings updated: ${id}`); setLastUpdated(Date.now()); // Sync with backend systems fetch('/api/tax-settings/updated', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ settingsId: id, timestamp: Date.now() }) }); // Show confirmation window.showNotification?.('success', 'Tax settings updated successfully'); }} onLoaderStart={({elementTagName}) => { console.log('Loading tax settings...'); }} onLoadError={({error}) => { console.error('Tax settings load error:', error); alert('Failed to load tax settings. Please try again.'); }} /> </div> ); }; export default TaxSettingsPage; ``` ## Document Management ### ConnectDocuments - Document Upload and Management Provides document upload and management interface for connected accounts. ```jsx import React, {useState} from 'react'; import {ConnectDocuments} from '@stripe/react-connect-js'; const DocumentsPage = () => { const [isLoading, setIsLoading] = useState(false); return ( <div className="documents-page"> <header className="documents-header"> <h1>Documents</h1> <p>Upload and manage verification documents</p> {isLoading && <div className="spinner">Loading...</div>} </header> <ConnectDocuments onLoaderStart={({elementTagName}) => { console.log('Loading documents component...'); setIsLoading(true); }} onLoadError={({error}) => { console.error('Documents load error:', error); setIsLoading(false); // Log error to monitoring service window.Sentry?.captureException(error, { tags: {component: 'documents'}, extra: {timestamp: Date.now()} }); }} /> </div> ); }; export default DocumentsPage; ``` ## Advanced Integration Examples ### Complete Dashboard with Multiple Components Full dashboard integration showing multiple Connect components working together. ```jsx import React, {useState} from 'react'; import {loadConnectAndInitialize} from '@stripe/connect-js'; import { ConnectComponentsProvider, ConnectBalances, ConnectPayments, ConnectPayouts, ConnectNotificationBanner, ConnectAccountManagement } from '@stripe/react-connect-js'; const Dashboard = () => { const [activeTab, setActiveTab] = useState('overview'); const [notificationCount, setNotificationCount] = useState(0); // Initialize Connect with custom appearance const fetchClientSecret = async () => { const response = await fetch('/api/account_session', { method: 'POST', headers: {'Content-Type': 'application/json'} }); const {client_secret} = await response.json(); return client_secret; }; const connectInstance = loadConnectAndInitialize({ publishableKey: process.env.REACT_APP_STRIPE_PUBLISHABLE_KEY, fetchClientSecret: fetchClientSecret, appearance: { variables: { colorPrimary: '#0066cc', colorBackground: '#f7f9fc', colorText: '#1a1a1a', colorDanger: '#cc0000', fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif', borderRadius: '8px' } } }); return ( <ConnectComponentsProvider connectInstance={connectInstance}> <div className="dashboard-layout"> <aside className="sidebar"> <nav> <button className={activeTab === 'overview' ? 'active' : ''} onClick={() => setActiveTab('overview')} > Overview </button> <button className={activeTab === 'payments' ? 'active' : ''} onClick={() => setActiveTab('payments')} > Payments </button> <button className={activeTab === 'payouts' ? 'active' : ''} onClick={() => setActiveTab('payouts')} > Payouts </button> <button className={activeTab === 'settings' ? 'active' : ''} onClick={() => setActiveTab('settings')} > Settings {notificationCount > 0 && ( <span className="badge">{notificationCount}</span> )} </button> </nav> </aside> <main className="content"> <ConnectNotificationBanner onNotificationsChange={({total, actionRequired}) => { setNotificationCount(actionRequired); }} onLoadError={({error}) => { console.error('Notification error:', error); }} /> {activeTab === 'overview' && ( <div className="overview-tab"> <h1>Dashboard Overview</h1> <ConnectBalances onLoadError={({error}) => { console.error('Balances error:', error); }} /> </div> )} {activeTab === 'payments' && ( <div className="payments-tab"> <h1>Payments</h1> <ConnectPayments defaultFilters={{status: ['succeeded']}} onLoadError={({error}) => { console.error('Payments error:', error); }} /> </div> )} {activeTab === 'payouts' && ( <div className="payouts-tab"> <h1>Payouts</h1> <ConnectPayouts onLoadError={({error}) => { console.error('Payouts error:', error); }} /> </div> )} {activeTab === 'settings' && ( <div className="settings-tab"> <h1>Account Settings</h1> <ConnectAccountManagement collectionOptions={{ fields: 'currently_due', futureRequirements: 'include' }} onLoadError={({error}) => { console.error('Settings error:', error); }} /> </div> )} </main> </div> </ConnectComponentsProvider> ); }; export default Dashboard; ``` ## Custom Hooks Integration ### useCreateComponent - Core Component Hook The internal hook that powers all Connect components, useful for building custom component wrappers. ```jsx import {useCreateComponent} from '@stripe/react-connect-js'; import {useUpdateWithSetter} from '@stripe/react-connect-js'; // Example: Creating a custom wrapper component const CustomPaymentsComponent = ({filters, onError}) => { const {wrapper, component} = useCreateComponent('payments'); // Use the setter utility to update component properties useUpdateWithSetter(component, filters, (comp, val) => { comp.setDefaultFilters(val); }); useUpdateWithSetter(component, onError, (comp, val) => { comp.setOnLoadError(val); }); return ( <div className="custom-wrapper"> <div className="custom-header">Custom Payments View</div> {wrapper} </div> ); }; // Usage const App = () => { return ( <CustomPaymentsComponent filters={{status: ['succeeded', 'pending']}} onError={({error}) => console.error(error)} /> ); }; export default App; ``` ## Error Handling and Monitoring ### Comprehensive Error Handling Pattern Best practices for handling errors across all Connect components with logging and user feedback. ```jsx import React, {useState, useCallback} from 'react'; import { ConnectComponentsProvider, ConnectPayments, ConnectAccountOnboarding } from '@stripe/react-connect-js'; import {loadConnectAndInitialize} from '@stripe/connect-js'; const ErrorBoundary = ({children}) => { const [error, setError] = useState(null); if (error) { return ( <div className="error-container"> <h2>Something went wrong</h2> <p>{error.message}</p> <button onClick={() => setError(null)}>Try Again</button> </div> ); } return children; }; const App = () => { const [globalError, setGlobalError] = useState(null); const [componentErrors, setComponentErrors] = useState({}); const handleLoadError = useCallback((component) => ({error, elementTagName}) => { console.error(`[${component}] Load error:`, error); // Log to monitoring service window.Sentry?.captureException(error, { tags: { component: component, elementTagName: elementTagName }, level: 'error' }); // Track in analytics window.analytics?.track('connect_component_error', { component: component, error: error.message, timestamp: Date.now() }); // Update local state setComponentErrors(prev => ({ ...prev, [component]: error.message })); // Show user-friendly message setGlobalError(`Failed to load ${component}. Please refresh the page or contact support.`); }, []); const fetchClientSecret = async () => { try { const response = await fetch('/api/account_session', { method: 'POST', headers: {'Content-Type': 'application/json'} }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const {client_secret} = await response.json(); return client_secret; } catch (error) { console.error('Failed to fetch client secret:', error); setGlobalError('Unable to initialize payment system. Please try again later.'); throw error; } }; const connectInstance = loadConnectAndInitialize({ publishableKey: process.env.REACT_APP_STRIPE_PUBLISHABLE_KEY, fetchClientSecret: fetchClientSecret, appearance: { variables: { colorPrimary: '#0066cc' } } }); return ( <ErrorBoundary> <ConnectComponentsProvider connectInstance={connectInstance}> {globalError && ( <div className="global-error"> <strong>Error:</strong> {globalError} <button onClick={() => setGlobalError(null)}>Dismiss</button> </div> )} <div className="app-content"> <ConnectPayments onLoadError={handleLoadError('payments')} onLoaderStart={() => { console.log('Payments loading...'); // Clear previous errors setComponentErrors(prev => ({...prev, payments: null})); }} /> {componentErrors.payments && ( <div className="component-error"> Error loading payments: {componentErrors.payments} </div> )} </div> </ConnectComponentsProvider> </ErrorBoundary> ); }; export default App; ``` ## Summary React Connect.js provides a declarative and type-safe way to integrate Stripe Connect embedded components into React applications. The library covers the complete spectrum of Connect functionality including payment processing, account onboarding, financial account management, issuing card operations, payout handling, tax compliance, and document management. Each component is designed to be composable and works seamlessly with React's component lifecycle and hooks system. The main integration pattern involves wrapping your application with `ConnectComponentsProvider`, initializing the Connect instance with your publishable key and a client secret fetching function, and then rendering individual Connect components as needed. All components support lifecycle callbacks for loading states and error handling, enabling robust production implementations with proper monitoring and user feedback. The library abstracts away DOM manipulation complexity while providing full access to component functionality through setter methods and event callbacks, making it ideal for building comprehensive financial dashboards, merchant onboarding flows, and payment management interfaces.