Wizards (multi-step forms) appear in checkout flows, onboarding, signup, settings. The interview tests whether you understand cross-step state management, validation strategies, and the UX details that make wizards feel polished vs frustrating.
Functional requirements
- Multiple steps, navigable in sequence — model steps as data (an array of step configs), not hardcoded JSX, so adding or reordering a step is a one-line change.
- Validation per step (cannot advance with errors) — validate only the current step’s fields on Next; don’t block the user with errors for fields they haven’t reached yet.
- Step indicator (1 of 5) — showing where the user is and how much remains measurably reduces abandonment on longer flows.
- Back button to return to previous step — going back must never wipe entered data, which is the most common trap interviewers set on this question.
- Save partial progress (e.g., refresh-tolerant) — persist state so a refresh or accidental tab close doesn’t force a restart; localStorage covers most cases, a server draft for high-value flows.
- Submit only after final step — nothing hits the real endpoint until the last step; earlier steps stay client-side or write to a draft.
State architecture
Single source of truth for all form data. Pass through context or a shared store.
React Hook Form has built-in support for nested forms; can register a master form across steps.
Step navigation
Two patterns:
- Linear: 1 → 2 → 3 → 4. User cannot skip. Keep the step order in one array and index into it, so next and back are just index math.
- Branching: path depends on earlier answers. “Are you a business?” yes → business steps; no → personal steps. Drive the branch off watched field values so the path recomputes when an earlier answer changes.
Validation per step
Each step has its own validation. Strategies:
- Validate on Next button click — trigger validation for the current step’s fields only; if any fail, block advancement and move focus to the first error.
- Allow free movement; flag invalid steps — let users jump around but mark incomplete steps in the indicator; good for edit-heavy flows like settings where people revisit.
- Async validation (server check) before allowing Next — for checks like username availability or coupon validity, show a pending state on Next and handle the request failing without trapping the user.
RHF + Zod provides good ergonomics. Each step defines its schema; combined schema validates the whole form on submit.
The “Back” question
Should clicking Back preserve user input on the current step? Almost always yes — frustrating otherwise.
If the form mutates server state at each step (rare): Back reverts the server state too, or stays at current step.
Step indicator
Common patterns:
- Numbered dots (“1 of 5”) — best for short, fixed flows; each dot can show done, current, and upcoming states.
- Progress bar (50% complete) — works when the step count is large or variable and individual step names don’t matter much.
- Step labels with active highlight (“Personal Info > Address > Payment”) — names each step so users anticipate what’s coming; make the labels clickable only when free navigation is allowed.
Show progress; reduce abandonment.
Persistence
If users abandon mid-wizard:
- Save to localStorage on each Next — serialize the whole form object under one key, and write on step change rather than every keystroke to avoid thrash.
- On return, restore state and offer “continue where you left off” — detect saved state on mount and prompt, rather than silently rehydrating and surprising the user with stale data.
- Clear after successful submission or after expiration window — delete the draft on submit and store a timestamp so week-old, likely-stale data isn’t restored.
For high-value flows (checkout): persist to server too.
Submission
Final step submits the entire form. Patterns:
- Disable submit during in-flight request — track a submitting flag, not just a spinner, so a double click can’t fire two submissions.
- Show loading state — give the button a spinner or “Submitting…” label so the user knows the click registered.
- On success: redirect or show confirmation — then clear the persisted draft so a back-navigation can’t resubmit.
- On failure: surface error, jump back to relevant step if needed — map server field errors back to their step and navigate there so the user fixes the exact field.
Accessibility
- Each step has its own form, heading, and field labels — give every step a real heading and associate every input with a label, since screen-reader users navigate by heading.
- aria-current on the current step in the indicator — set aria-current=”step” so assistive tech announces the user’s position in the sequence.
- Focus management: when advancing, focus moves to first field of new step — otherwise keyboard users are stranded on the Next button after each transition.
- Errors announced via aria-live — put the error summary in an aria-live=”polite” region so new errors are read aloud without stealing focus.
Mobile considerations
- One screen per step (vertical layout) — single column, one task per screen; avoid side-by-side fields that force horizontal scrolling on phones.
- Sticky bottom buttons (Back / Next) — pin them so the user never has to scroll to find how to advance.
- Keyboard avoidance for inputs — make the focused field scroll above the on-screen keyboard instead of hiding behind it.
- Numeric keyboard for number fields — set inputmode=”numeric” (and type=”tel” for codes) so phones show the number pad rather than the full keyboard.
Step transitions
Subtle slide animation between steps gives a feeling of progress. Don’t over-animate; 200–300ms is plenty.
Common antipatterns
- Lose data on back navigation — keep all step data in one store so unmounting a step component never discards its values.
- Validation only on submit (user discovers all errors at end) — someone fills five steps, then gets sent back to step one; validate per step instead.
- Required fields not labeled clearly — mark required fields visibly, not by color alone, and state the rule before the user submits.
- No progress indicator — without a sense of length users abandon; even a plain “Step 2 of 4” helps.
- Confirmation modal blocking the user from changing their mind — don’t trap people in a confirm dialog with no easy path back to edit their answers.
Frequently Asked Questions
How many steps is too many?
5–7 is the sweet spot. Above 10, users abandon. Combine logically related fields per step.
Should the back button preserve the URL state?
For long flows: yes — use URL query params for the current step. Browser back works as expected.
How do I handle wizards with conditional steps?
Maintain a step graph; compute next/previous based on current state. React Hook Form’s field watchers help.
Useful next steps:
