Stripe Apps の OnboardingView コンポーネント公開プレビュー
OnboardingView を使用して Stripe アプリのアカウント登録フローを実装する
OnboardingView コンポーネントをアプリに追加するには、以下のようにします。
import {OnboardingView} from '@stripe/ui-extension-sdk/ui';
OnboardingView コンポーネントは、事前定義された構造を持つアカウント登録ビューを実装するための、標準化された方法を提供します。
- アカウント登録タスクのリストを表示する左のサイドバー
- 特定のアカウント登録ステップのコンテンツを表示するメインコンテンツエリア
アカウント登録タスクのリストは、TaskListItemProps 項目の配列として指定します。カスタムの React ビューを <OnboardingView> の直接の子として指定することで、アカウント登録ステップ自体のコンテンツを全面的にカスタマイズできます。このアプローチを使用すると、Stripe ダッシュボードでアカウント登録タスクのリストの表示方法を制御しながら、ビジネスニーズに基づいてカスタムのアカウント登録ステップを実装できます。
OnboardingView プロパティ
| プロパティ | タイプ |
|---|---|
| 必要
プライマリー列のコンテンツをレンダリングする React コンポーネント。 |
| 必要
すべてのユーザー登録タスクが完了したかどうか。true に設定すると、ユーザー登録モーダルウィンドウは、ユーザーが以前の場所に戻るために少し遅れた後に自動的に閉じます。 |
| 必要
アカウント登録タスクのリスト。 関連型: Tasks。 |
| 必要
アカウント登録ステップのタイトル。 |
| オプション
アカウント登録ステップの説明。 |
| オプション
ユーザ登録中に発生したエラーに関する情報。 |
| オプション
ユーザ登録フローが読み込み中かどうか。true の場合はスピナーと読み込み中メッセージを表示します。 |
タスク
| プロパティ | タイプ |
|---|---|
| 必要
タスクの表示タイトル。 |
| オプション
ユーザーがタスク上の任意の場所をクリックしたときのイベントハンドラー。 |
| オプション
タスクの現在のステータス。 |
| オプション
このタスクに属するサブタスクのリスト。 関連型: SubTasks。 |
SubTasks
| プロパティ | タイプ |
|---|---|
| 必要
タスクの表示タイトル。 |
| オプション
ユーザーがタスク上の任意の場所をクリックしたときのイベントハンドラー。 |
| オプション
タスクの現在のステータス。 |
基本
以下の例は、OnboardingView コンポーネントの基本的な使用方法を示しています。ここでは、アカウント登録ステップごとに異なる React ビューが表示されます。
import React, {useState, useReducer, useCallback} from 'react'; import { FormFieldGroup, TextField, OnboardingView, Switch, TaskListItemProps, } from '@stripe/ui-extension-sdk/ui'; const onboardingTasks: Record<TaskName, TaskListItemProps> = { addInfo: { title: 'Add business info', status: 'in-progress', onPress: () => handlePress('addInfo'), }, connectBank: { title: 'Connect your bank', status: 'not-started', onPress: () => handlePress('connectBank'), }, review: { title: 'Review and finish', status: 'not-started', onPress: () => handlePress('review'), }, }; // These view implement the UI required by a particular onboarding step const steps: Record<TaskName, React.FunctionComponent> = { addInfo: () => ( <FormFieldGroup legend="Business Info" description="Add business info"> <TextField label="Company name" placeholder="Company name" hiddenElements={['label']} /> </FormFieldGroup> ), connectBank: () => ( <FormFieldGroup legend="Connect your bank" description="Enter the bank account to which withdrawals will be sent." > <TextField label="Bank name" placeholder="Bank name" hiddenElements={['label']} /> </FormFieldGroup> ), review: () => ( <FormFieldGroup legend="Specify settings" layout="vertical"> <Switch label="Enable automatic transfers" description="Enable automatic transfers" /> <Switch label="Enable auto-import of transactions" description="Enable auto-import of transactions" /> </FormFieldGroup> ), }; const handlePress = useCallback((taskName: TaskName) => { setTaskName(taskName); dispatch({type: 'TOGGLE_STATUS', taskName}); }, []); const [taskName, setTaskName] = useState<TaskName>('addInfo'); const [tasks, dispatch] = useReducer(taskReducer, onboardingTasks); const taskListItems = Object.values(tasks); const title = tasks[taskName].title; const description = `Please complete the onboarding step.`; const completed = taskListItems.every((item) => item.status === 'complete'); const OnboardingViewContent = steps[taskName]; return ( <OnboardingView title={title} description={description} completed={completed} tasks={taskListItems} > <OnboardingViewContent /> </OnboardingView> ); function getNextStatus( status: string, ): 'not-started' | 'in-progress' | 'complete' { switch (status) { case 'complete': return 'not-started'; case 'not-started': return 'in-progress'; case 'in-progress': return 'complete'; default: return 'not-started'; } } type TaskName = 'addInfo' | 'connectBank' | 'review'; type TaskAction = { type: 'TOGGLE_STATUS'; taskName: TaskName; }; // Reducer function to handle state updates function taskReducer( state: Record<TaskName, TaskListItemProps>, action: TaskAction, ): Record<TaskName, TaskListItemProps> { switch (action.type) { case 'TOGGLE_STATUS': return { ...state, [action.taskName]: { ...state[action.taskName], status: getNextStatus(state[action.taskName].status as string), }, }; default: return state; } }
移行
この例は、ユーザ登録フロー中にerror プロパティとpending プロパティを使用してさまざまな状態を処理する方法を示しています。
このコンポーネントは、次の 3 つの異なる状態を管理します。
- 保留中: ユーザ登録データの取得中に読み込みスピナーを表示します
- エラー: データ取得が失敗した場合に再試行ボタンを表示します
- 準備完了: タスクとフォームを使用して通常のユーザ登録操作をレンダリングします
サンプルコンポーネントが最初に読み込まれると、データ取得の失敗がシミュレーションされ、エラー状態が実証されます。再試行 をクリックすると、データ取得が成功し、実際のユーザー登録コンテンツが表示されます。このアプローチにより、追加のコンポーネントや複雑な状態管理を必要とせずに、読み込み時とエラー時の各種シナリオをスムーズに処理できます。
import React, {useCallback, useEffect, useState} from 'react'; import { FormFieldGroup, TextField, Button, OnboardingView, TaskListItemProps, } from '@stripe/ui-extension-sdk/ui'; type OnboardingData = { state: 'pending' | 'error' | 'ready'; tasks: TaskListItemProps[]; }; const [onboarding, setOnboarding] = useState<OnboardingData>({ state: 'pending', tasks: [], }); const fetchTasks = useCallback( (() => { let isFirstTry = true; return () => { setOnboarding({state: 'pending', tasks: []}); setTimeout(() => { if (isFirstTry) { isFirstTry = false; setOnboarding((prev) => ({...prev, state: 'error'})); } else { setOnboarding({ state: 'ready', tasks: [ {title: 'Add business info', status: 'in-progress'}, {title: 'Connect your bank', status: 'not-started'}, {title: 'Review and finish', status: 'not-started'}, ], }); } }, 2000); }; })(), [], ); useEffect(fetchTasks, [fetchTasks]); const error = onboarding.state === 'error' ? ( <Button onPress={fetchTasks}>Try again!</Button> ) : null; const pending = onboarding.state === 'pending'; return ( <OnboardingView error={error} pending={pending} title="Onboarding title" description="Onboarding description" completed={false} tasks={onboarding.tasks} > <FormFieldGroup legend="Business Info" description="Add business info!"> <TextField label="Company name" placeholder="Company name" hiddenElements={['label']} /> </FormFieldGroup> </OnboardingView> )