React Step FormExamples
React Step FormExamples
Usage
Common patterns for building complex multi-step flows.
Usage
Navigation actions
Use useFormWizard() to read state and drive navigation from any child.
import { useFormWizard } from "@avenra/react-step-form";
export function StepActions() {
const { next, prev, isFirstStep, isLastStep, progress } = useFormWizard();
return (
<div>
<small>{progress}% complete</small>
<button type="button" onClick={prev} disabled={isFirstStep}>
Back
</button>
<button type="button" onClick={next} disabled={isLastStep}>
Next
</button>
</div>
);
}Step fields
You can define step fields explicitly to control what validates per step.
<FormWizard
schema={schema}
steps={[
{
id: "account",
component: AccountStep,
fields: ["email", "password"],
},
{
id: "profile",
component: ProfileStep,
fields: ["firstName", "lastName"],
},
]}
onSubmit={handleSubmit}
/>If you omit fields, the wizard infers them from mounted Controller usage.
Nested values
Controllers accept nested field paths for structured schemas.
type Values = z.infer<typeof schema>;
const TypedController = Controller<Values>;
<TypedController
name="account.email"
render={({ field }) => <input type="email" {...field} />}
/>;Read values reactively
watch() returns the full state or a single field value.
const { watch } = useFormWizard<Values>();
const fullValues = watch();
const email = watch("account.email");Custom layout
Use the render prop to build any layout or button placement you want.
<FormWizard schema={schema} steps={steps} onSubmit={handleSubmit}>
{({ currentStep, canGoPrev, canGoNext, prev, next, submit }) => (
<div className="wizard">
<header>{currentStep.id}</header>
<currentStep.component />
<footer>
<button type="button" onClick={prev} disabled={!canGoPrev}>
Back
</button>
<button type="button" onClick={next} disabled={!canGoNext}>
Continue
</button>
<button type="button" onClick={submit}>
Submit
</button>
</footer>
</div>
)}
</FormWizard>