Avenra
React Step FormGetting Started
React Step FormGetting Started

Quick start

Build your first multi-step form with @avenra/react-step-form.

React Step Form is a headless wizard engine for multi-step forms. You provide a single schema, define steps, and render your own UI with a render prop.

Basic wizard

This example uses Zod for schema-driven validation and the Controller component to wire inputs.

import * as z from "zod";
import { Controller, FormWizard } from "@avenra/react-step-form";

const signupSchema = z.object({
    email: z.string().email("Enter a valid email"),
    password: z.string().min(6, "Min 6 characters"),
    firstName: z.string().min(1, "First name is required"),
    lastName: z.string().min(1, "Last name is required"),
});

type SignupValues = z.infer<typeof signupSchema>;
const TypedController = Controller<SignupValues>;

function AccountStep() {
    return (
        <section>
            <TypedController
                name="email"
                render={({ field, fieldState }) => (
                    <label>
                        Email
                        <input type="email" {...field} />
                        {fieldState.error ? <p>{fieldState.error}</p> : null}
                    </label>
                )}
            />

            <TypedController
                name="password"
                render={({ field, fieldState }) => (
                    <label>
                        Password
                        <input type="password" {...field} />
                        {fieldState.error ? <p>{fieldState.error}</p> : null}
                    </label>
                )}
            />
        </section>
    );
}

function ProfileStep() {
    return (
        <section>
            <TypedController
                name="firstName"
                render={({ field }) => (
                    <input placeholder="First name" {...field} />
                )}
            />
            <TypedController
                name="lastName"
                render={({ field }) => (
                    <input placeholder="Last name" {...field} />
                )}
            />
        </section>
    );
}

export function SignupWizard() {
    return (
        <FormWizard
            schema={signupSchema}
            defaultValues={{
                email: "",
                password: "",
                firstName: "",
                lastName: "",
            }}
            steps={[
                { id: "account", component: AccountStep },
                { id: "profile", component: ProfileStep },
            ]}
            onSubmit={(values) => console.log("submit", values)}
        >
            {({ currentStep, isFirstStep, isLastStep, prev, next, submit }) => (
                <main>
                    <currentStep.component />
                    <button type="button" onClick={prev} disabled={isFirstStep}>
                        Back
                    </button>
                    {!isLastStep ? (
                        <button type="button" onClick={next}>
                            Next
                        </button>
                    ) : (
                        <button type="button" onClick={submit}>
                            Submit
                        </button>
                    )}
                </main>
            )}
        </FormWizard>
    );
}

Next steps

  • Learn step-level validation in the Validation guide.
  • Explore component APIs in Components.
  • Add persistence and debug tooling when needed.

On this page