关于 onboardjs-react
onboardjs-react 是使用 OnboardJS 构建引导流程的 React 集成指南,面向需要自定义界面并由库处理流程状态与导航的开发者。
主要功能
- 01React 项目与包管理器检测
- 02步骤组件和 Provider 配置
- 03用于渲染与导航的引导 Hook
- 04通过步骤 ID 跟踪进度
- 05Next.js 客户端设置与延迟加载
- 06本地及自定义后端持久化
适用场景
- 01为 React 应用添加引导流程
- 02将引导设置适配到 Next.js
- 03跟踪引导步骤进度
- 04通过本地存储或 API 保存引导状态
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ onboardjs/ onboardjs-skills --skill onboardjs-react安装后在 Claude Code 中输入/onboardjs-react确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/hooks-api.mdpatterns.mdstep-config.md详细介绍
OnboardJS React 集成
OnboardJS 是一个用于构建用户引导体验的无界面库。你可以控制 UI;OnboardJS 负责处理流程逻辑、状态、持久化和导航。
开始之前
1. 确认 React 项目 - 检查是否存在包含 React 依赖项的 package.json。如果不是 React 项目,请告知用户。
2. 检测包管理器 - 检查锁定文件,以确定正确的安装命令:
| 锁定文件 | 包管理器 | 安装命令 |
|---|---|---|
pnpm-lock.yaml | pnpm | pnpm add @onboardjs/core @onboardjs/react |
yarn.lock | yarn | yarn add @onboardjs/core @onboardjs/react |
bun.lockb | bun | bun add @onboardjs/core @onboardjs/react |
package-lock.json 或无锁定文件 | npm | npm install @onboardjs/core @onboardjs/react |
3. 检测 Next.js - 检查是否存在 next.config.js、next.config.mjs,或依赖项中是否包含 next。如果是 Next.js 项目,请参阅Next.js 设置部分。
安装
# npm
npm install @onboardjs/core @onboardjs/react
# pnpm
pnpm add @onboardjs/core @onboardjs/react
# yarn
yarn add @onboardjs/core @onboardjs/react
# bun
bun add @onboardjs/core @onboardjs/react
快速设置
1. 使用组件定义步骤
// steps.tsx
import { OnboardingStep } from '@onboardjs/react'
import { WelcomeStep } from './components/WelcomeStep'
import { ProfileFormStep } from './components/ProfileFormStep'
import { CompleteStep } from './components/CompleteStep'
const steps: OnboardingStep[] = [
{
id: 'welcome',
component: WelcomeStep,
payload: { title: 'Welcome!', description: 'Let\'s get started' },
nextStep: 'profile'
},
{
id: 'profile',
component: ProfileFormStep,
nextStep: 'complete'
},
{
id: 'complete',
component: CompleteStep,
payload: { title: 'All done!' },
nextStep: null
}
]
2. 使用 Provider 包装
import { OnboardingProvider } from '@onboardjs/react'
import { steps } from './steps'
function App() {
return (
<OnboardingProvider
steps={steps}
onFlowComplete={(ctx) => console.log('Done!', ctx)}
>
<OnboardingUI />
</OnboardingProvider>
)
}
3. 使用 Hook
import { useOnboarding } from '@onboardjs/react'
function OnboardingUI() {
const { renderStep, next, previous, state, loading } = useOnboarding()
if (loading.isHydrating) return <Spinner />
if (state?.isCompleted) return <CompletedScreen />
return (
<div>
{renderStep()}
<div>
<button onClick={previous} disabled={state?.isFirstStep}>Back</button>
<button onClick={() => next()} disabled={!state?.canGoNext}>
{state?.isLastStep ? 'Finish' : 'Next'}
</button>
</div>
</div>
)
}
步骤指示器 / 进度
重要: state 对象没有 steps 数组。请使用 currentStepNumber 和 totalSteps,或根据步骤 ID 进行计算。
选项 1:使用内置属性(如果可用)
function OnboardingUI() {
const { state, renderStep } = useOnboarding()
return (
<div>
{state?.currentStepNumber && state?.totalSteps && (
<div>Step {state.currentStepNumber} of {state.totalSteps}</div>
)}
<progress
value={state?.currentStepNumber ?? 0}
max={state?.totalSteps ?? 1}
/>
{renderStep()}
</div>
)
}
选项 2:根据步骤 ID 计算(推荐)
若要可靠地跟踪进度,请定义一次步骤 ID 并计算索引:
// steps.tsx - export your step IDs
export const STEP_IDS = ['welcome', 'profile', 'preferences', 'complete'] as const
export const steps: OnboardingStep[] = [
{ id: 'welcome', component: WelcomeStep, nextStep: 'profile' },
{ id: 'profile', component: ProfileStep, nextStep: 'preferences' },
{ id: 'preferences', component: PreferencesStep, nextStep: 'complete' },
{ id: 'complete', component: CompleteStep, nextStep: null }
]
// OnboardingUI.tsx
import { STEP_IDS } from './steps'
function OnboardingUI() {
const { state, renderStep } = useOnboarding()
const currentIndex = STEP_IDS.findIndex(id => id === state?.currentStep?.id)
const currentStepNumber = currentIndex + 1
const totalSteps = STEP_IDS.length
return (
<div>
<div>Step {currentStepNumber} of {totalSteps}</div>
<progress value={currentStepNumber} max={totalSteps} />
{renderStep()}
</div>
)
}
步骤指示器组件
interface StepIndicatorProps {
stepIds: readonly string[]
currentStepId: string | undefined
}
function StepIndicator({ stepIds, currentStepId }: StepIndicatorProps) {
const currentIndex = stepIds.findIndex(id => id === currentStepId)
return (
<div className="flex gap-2">
{stepIds.map((id, index) => (
<div
key={id}
className={`w-3 h-3 rounded-full ${
index < currentIndex ? 'bg-green-500' :
index === currentIndex ? 'bg-blue-500' :
'bg-gray-300'
}`}
/>
))}
</div>
)
}
// Usage
<StepIndicator stepIds={STEP_IDS} currentStepId={state?.currentStep?.id} />
步骤组件模式
import { StepComponentProps } from '@onboardjs/react'
interface ProfilePayload {
title: string
fields: string[]
}
const ProfileFormStep: React.FC<StepComponentProps<ProfilePayload>> = ({
payload,
context,
onDataChange,
initialData
}) => {
const [name, setName] = useState(initialData?.name || '')
const handleChange = (value: string) => {
setName(value)
onDataChange?.({ name: value }, value.length > 0)
}
return (
<div>
<h2>{payload.title}</h2>
<input value={name} onChange={(e) => handleChange(e.target.value)} />
</div>
)
}
Next.js 设置
OnboardJS 使用 React Hooks 和浏览器 API,因此在 Next.js App Router 中需要客户端渲染。
步骤组件 - 添加 "use client"
所有步骤组件都必须是客户端组件:
// components/WelcomeStep.tsx
'use client'
import { StepComponentProps } from '@onboardjs/react'
export const WelcomeStep: React.FC<StepComponentProps> = ({ payload }) => {
return <h1>{payload.title}</h1>
}
Provider 包装器 - 添加 "use client"
为 Provider 创建一个客户端包装器:
// components/OnboardingWrapper.tsx
'use client'
import { OnboardingProvider } from '@onboardjs/react'
import { steps } from './steps'
export function OnboardingWrapper({ children }: { children: React.ReactNode }) {
return (
<OnboardingProvider
steps={steps}
onFlowComplete={(ctx) => console.log('Done!', ctx)}
>
{children}
</OnboardingProvider>
)
}
在页面中使用(App Router)
// app/onboarding/page.tsx
import { OnboardingWrapper } from '@/components/OnboardingWrapper'
import { OnboardingUI } from '@/components/OnboardingUI'
export default function OnboardingPage() {
return (
<OnboardingWrapper>
<OnboardingUI />
</OnboardingWrapper>
)
}
动态导入(可选 - 用于代码拆分)
使用动态导入以减小初始包体积:
// app/onboarding/page.tsx
import dynamic from 'next/dynamic'
const OnboardingWrapper = dynamic(
() => import('@/components/OnboardingWrapper').then(mod => mod.OnboardingWrapper),
{
ssr: false,
loading: () => <div>Loading onboarding...</div>
}
)
export default function OnboardingPage() {
return <OnboardingWrapper><OnboardingUI /></OnboardingWrapper>
}
动态步骤组件(可选 - 用于大型流程)
延迟加载步骤组件以减小包体积:
// steps.tsx
'use client'
import dynamic from 'next/dynamic'
import { OnboardingStep } from '@onboardjs/react'
const WelcomeStep = dynamic(() => import('./components/WelcomeStep').then(m => m.WelcomeStep))
const ProfileStep = dynamic(() => import('./components/ProfileStep').then(m => m.ProfileStep))
const CompleteStep = dynamic(() => import('./components/CompleteStep').then(m => m.CompleteStep))
export const steps: OnboardingStep[] = [
{ id: 'welcome', component: WelcomeStep, nextStep: 'profile' },
{ id: 'profile', component: ProfileStep, nextStep: 'complete' },
{ id: 'complete', component: CompleteStep, nextStep: null }
]
Pages Router(旧版)
对于 Next.js Pages Router,无需使用 "use client",但要禁用 SSR:
// pages/onboarding.tsx
import dynamic from 'next/dynamic'
const OnboardingFlow = dynamic(
() => import('@/components/OnboardingFlow'),
{ ssr: false }
)
export default function OnboardingPage() {
return <OnboardingFlow />
}
持久化
localStorage(简单方式)
<OnboardingProvider
steps={steps}
localStoragePersistence={{ key: 'onboarding_v1', ttl: 604800000 }}
>
自定义后端
<OnboardingProvider
steps={steps}
customOnDataLoad={async () => await fetchFromAPI()}
customOnDataPersist={async (ctx) => await saveToAPI(ctx)}
customOnClearPersistedData={async () => await clearAPI()}
>
条件导航
import { RoleSelectStep } from './components/RoleSelectStep'
import { AdminSetupStep } from './components/AdminSetupStep'
import { UserSetupStep } from './components/UserSetupStep'
{
id: 'role-select',
component: RoleSelectStep,
payload: {
options: [
{ value: 'admin', label: 'Admin' },
{ value: 'user', label: 'User' }
]
},
nextStep: (ctx) => ctx.flowData.role === 'admin' ? 'admin-setup' : 'user-setup'
}
条件步骤可见性
{
id: 'admin-setup',
component: AdminSetupStep,
condition: (ctx) => ctx.flowData.role === 'admin'
}
进阶:参阅参考资料
- references/step-config.md - 完整的步骤配置选项
- references/hooks-api.md - 完整的 useOnboarding API
- references/patterns.md - 进阶模式(验证、事件、插件、Next.js)
评论
支持 Markdown