简单 wizard
React 18和19的轻量级,灵活的向导组件.
安装
npm install @d1os/simple-wizard
yarn add @d1os/simple-wizard
pnpm add @d1os/simple-wizard
快速启动
import { Wizard, useWizard } from "@d1os/simple-wizard";
function App() {
return (
<Wizard footer={<WizardFooter />}>
<StepOne />
<StepTwo />
<StepThree />
</Wizard>
);
}
function WizardFooter() {
const { nextStep, previousStep, activeStep, stepCount } = useWizard((state) => ({
nextStep: state.nextStep,
previousStep: state.previousStep,
activeStep: state.activeStep,
stepCount: state.stepCount,
}));
const isFirstStep = activeStep === 0;
const isLastStep = activeStep === stepCount - 1;
return (
<div>
<button onClick={() => previousStep()} disabled={isFirstStep}>
Back
</button>
<button onClick={() => nextStep()} disabled={isLastStep}>
{isLastStep ? "Finish" : "Next"}
</button>
</div>
);
}
API 密码
<Wizard />
主要集装箱部分.
interface WizardProps {
children?: ReactNode; // Step components
header?: ReactNode; // Rendered before steps
footer?: ReactNode; // Rendered after steps
startAtEnd?: boolean; // Start at last step (default: false)
initialStep?: number; // Starting step index (default: 0)
}
useWizard(selector)
钩入巫师状态和行动。 使用选择器进行最佳重置.
const { activeStep, nextStep } = useWizard((state) => ({
activeStep: state.activeStep,
nextStep: state.nextStep,
}));
状态
| 财产 | 类型 | 说明 |
|---|---|---|
activeStep | number | 当前步骤指数(基于0) |
stepCount | number | 步骤总数 |
isLoading | boolean | 在同步动作中加载状态 |
nextButtonLabel | string | 下一个按钮的标签( 默认为“ 下一步 ”) |
previousButtonLabel | string | 上一个按钮的标签( 默认为“ 返回 ”) |
isNextButtonDisabled | boolean | 是否禁用下一个按钮 |
行动
| 行动 | 类型 | 说明 |
|---|---|---|
nextStep(skip?) | (skip?: number) => void | 转到下一步( 或跳过多个步骤) |
previousStep(skip?) | (skip?: number) => void | 跳转到上一步( 或跳过多步) |
setActiveStep(step) | (step: number) => void | 跳到特定的步骤 |
setIsLoading(loading) | (loading: boolean) => void | 设定装入状态 |
setStepAction(handler) | (handler: () => void | Promise<void>) => void | 在推进前设定要运行的动作 |
setNextButtonLabel(label) | (label: string) => void | 设置下个按钮标签 |
setPreviousButtonLabel(label) | (label: string) => void | 设置上一个按钮标签 |
setNextButtonDisabled(disabled) | (disabled: boolean) => void | 禁用/ 可启用下一个按钮 |
实例
Async 步骤验证
在推进下一步前运行同步验证 :
function StepWithValidation() {
const { setStepAction } = useWizard((state) => ({
setStepAction: state.setStepAction,
}));
useEffect(() => {
setStepAction(async () => {
await saveFormData();
// If this throws, navigation is cancelled
});
}, [setStepAction]);
return <form>...</form>;
}
有条件跳过步骤
使用 skip 有条件跳过步骤的道具 :
<Wizard>
<StepOne />
<StepTwo skip={!showOptionalStep} />
<StepThree />
</Wizard>
自定义进度指标
function ProgressBar() {
const { activeStep, stepCount } = useWizard((state) => ({
activeStep: state.activeStep,
stepCount: state.stepCount,
}));
const progress = ((activeStep + 1) / stepCount) * 100;
return (
<div className="progress-bar">
<div className="progress-fill" style={{ width: `${progress}%` }} />
<span>{activeStep + 1} of {stepCount}</span>
</div>
);
}
// Usage
<Wizard header={<ProgressBar />}>
...
</Wizard>
控制导航
function StepButtons() {
const { activeStep, stepCount, setActiveStep } = useWizard((state) => ({
activeStep: state.activeStep,
stepCount: state.stepCount,
setActiveStep: state.setActiveStep,
}));
return (
<div className="step-buttons">
{Array.from({ length: stepCount }, (_, i) => (
<button
key={i}
onClick={() => setActiveStep(i)}
className={activeStep === i ? "active" : ""}
>
{i + 1}
</button>
))}
</div>
);
}
使用窗体库
simple-wizard 是形式-图书馆不可知论。 您可以使用任何您喜欢的表格库, 例如 react-hook-form, (中文(简体) ), formik, (中文(简体) ), @tanstack/react-form等 (中文(简体) ).
使用 setStepAction() 整合验证:
使用 react-hook-form
import { useForm } from "react-hook-form";
function StepWithValidation() {
const { register, trigger } = useForm();
const { setStepAction } = useWizard((state) => ({
setStepAction: state.setStepAction,
}));
useEffect(() => {
setStepAction(async () => {
const valid = await trigger();
if (!valid) {
throw new Error("Form is invalid");
}
});
}, [setStepAction, trigger]);
return (
<input {...register("email", { required: true })} placeholder="Email" />
);
}
使用 @tanstack/react-form
import { useForm } from "@tanstack/react-form";
function StepWithValidation() {
const form = useForm({
defaultValues: {
email: "",
},
});
const { setStepAction } = useWizard((state) => ({
setStepAction: state.setStepAction,
}));
useEffect(() => {
setStepAction(async () => {
await form.validateAllFields("change");
if (!form.state.isFormValid) {
throw new Error("Form is invalid");
}
});
}, [setStepAction, form]);
return (
<form.Field name="email">
{({ field }) => (
<input {...field.getInputProps()} placeholder="Email" />
)}
</form.Field>
)
}
一个使用 @tanstack/react-form 可见于 这个堆起闪烁。 。 。 .
反应19 最佳做法
这个库与React 19完全兼容. 这里的图案可以利用步骤组件中的19个特性:
使用 use() 用于获取数据
import { use, Suspense } from "react";
function StepWithData({ dataPromise }) {
const data = use(dataPromise);
return <div>{data.content}</div>;
}
// In your wizard
<Wizard>
<Suspense fallback={<Loading />}>
<StepWithData dataPromise={fetchStepData()} />
</Suspense>
</Wizard>
优化更新 useOptimistic()
import { useOptimistic, useState } from "react";
function StepWithOptimisticSave() {
const [saved, setSaved] = useState(false);
const [optimisticSaved, setOptimisticSaved] = useOptimistic(saved);
async function handleSave() {
setOptimisticSaved(true); // Instant UI feedback
await saveToServer();
setSaved(true);
}
return (
<div>
<button onClick={handleSave}>
{optimisticSaved ? "Saved!" : "Save"}
</button>
</div>
);
}
表格动作 useActionState()
import { useActionState } from "react";
function FormStep() {
const [state, submitAction, isPending] = useActionState(
async (prevState, formData) => {
const result = await submitForm(formData);
return { success: result.ok, error: result.error };
},
{ success: false, error: null }
);
return (
<form action={submitAction}>
<input name="email" type="email" required />
{state.error && <p className="error">{state.error}</p>}
<button type="submit" disabled={isPending}>
{isPending ? "Submitting..." : "Continue"}
</button>
</form>
);
}
类型脚本
导出类型的全类型脚本支持 :
import type {
WizardProps,
WizardStore,
WizardState,
WizardActions
} from "@d1os/simple-wizard";
许可证
麻省理工学院