renderpx
Theme: auto

Multi-Step Forms

Break long forms into steps so users see one chunk at a time, with progress, per-step validation, and optional draft persistence.

The problem I keep seeing

Checkout, onboarding, and long surveys often dump many fields on one page. Users get overwhelmed, abandon halfway, or hit submit only to see a wall of validation errors. You need a way to break the form into steps, validate each step before advancing, and optionally persist a draft so they can leave and come back.

Naive approach

One giant form with every field and a single submit. Simple to wire, but poor UX: no sense of progress, and validation fires for everything at once at the end.

tsx
Loading...

First improvement

A wizard: keep a stepIndex (or step id) in state, render only the fields for the current step, and provide Next/Back. The user sees one logical “page” at a time and progress is clear.

tsx
Loading...

Remaining issues

  • Per-step validation: Validate only the current step before allowing “Next”; don’t run the full schema until the final submit.
  • URL sync: Put the step in the URL (e.g. ?step=shipping) so the user can bookmark, share, or use the back button and land on the right step.
  • Draft: Persist form values (localStorage or API) so leaving the page doesn’t lose data; restore on return.

Production pattern

Use React Hook Form with FormProvider so all step components share the same form state. Derive the current step from useSearchParams so the URL is the source of truth. Before advancing, call trigger(fieldsForThisStep); only move to the next step if validation passes. Optionally persist a draft (e.g. debounced form.watch → localStorage or PATCH draft endpoint) and clear it on successful submit.

tsx
Loading...
Optional: persist drafttsx
Loading...

When I use this

  • Checkout / long forms: 3–7 logical steps (details → shipping → payment) with clear progress and per-step validation.
  • Onboarding: One or two questions per step to reduce drop-off.
  • Skip when: Form has fewer than ~5–7 fields; a single page with good grouping and validation is enough.

Gotchas

  • Step in URL: Normalize invalid or missing step to the first step so direct links don’t break.
  • Back button: If step is in the URL, browser back naturally goes to the previous step; don’t block it.
  • Draft key: Use a key that includes user/session if multiple drafts exist (e.g. 'draft-' + userId).

Form Validation → · All patterns