tezvyn:

Design a multi-step wizard form pattern in React

AI-drafted, machine-checkedSource: blog.logrocket.comadvanced
Design a multi-step wizard form pattern in React
WHAT IT TESTS

shared state, step validation, and resilient navigation. A great answer uses one form instance with per-step Zod schemas, a context stepper, and localStorage persistence. Red flag: isolated forms per step that lose data on navigation.

WHAT THIS TESTS: This question probes whether you can separate orchestration from presentation in a complex React form. The interviewer cares about state cohesion, validation timing, and UX resilience when users move non-linearly through a flow.

A GOOD ANSWER COVERS four things in order. First, a single form instance at the wizard root using React Hook Form with a defaultValues object that holds the entire shape, so every step writes into the same field registry. Second, per-step Zod schema slices that are composed into a master schema; the nextStep handler triggers schema.safeParse on only the current step's fields before incrementing the index, preventing progress on invalid input. Third, a lightweight context or custom hook that exposes the current step index, a goToStep function guarded by validation state, and derived metadata like isFirstStep or isLastStep so the shell controls navigation. Fourth, persistence via localStorage or sessionStorage using a useEffect or a library like Mantine Hooks to hydrate defaultValues on mount and debounce saves on change, preventing data loss on accidental refresh.

COMMON WRONG ANSWERS: Treating each step as an independent form with its own useState and submit handler, which forces you to stitch data together at the end and breaks back-navigation validation. Another red flag is validating the entire schema on every step change, which surfaces errors for untouched future fields. A third is using URL query params for step index without guarding direct access to later steps, letting users skip required validation.

LIKELY FOLLOW-UPS: How would you handle conditional steps that appear based on earlier answers? The answer should mention dynamic step arrays and unregistering fields when branches change. How do you prevent double submission? Mention disabling the submit button via formState.isSubmitting. What if a step has async validation like checking username availability? Describe using the resolver with async refinements or manual trigger calls.

ONE CONCRETE EXAMPLE: Imagine a checkout wizard with shipping, payment, and review steps. The root component wraps the form in FormProvider and renders the active step by array index. The shipping step uses Zod to enforce address fields; on click next, the resolver validates only those fields. If the user refreshes at step two, a useLocalStorage hook repopulates defaultValues from cache. The review step reads all cached data from the single form state and submits once.

Source: blog.logrocket.com

Read the original → blog.logrocket.com

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.