Avenra
React Step FormExamples
React Step FormExamples

Usage

Common patterns for building complex multi-step flows.

Usage

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>

On this page