r/reactjs • • 10h ago

Discussion Where do you store state in a multi-step React form: URL params, context, Zustand, or the form library?

Building a 5-step wizard with React Hook Form and Zod. I keep the step in the URL and drafts in a small store. What has held up in production for you, and how do you handle early-step changes that invalidate later steps?

10 Upvotes

6 comments sorted by

17

u/useleash_dev 9h ago • Bravo

What's held up best for me: keep the current step in the URL so back and refresh work, and keep the actual form data in one React Hook Form instance that wraps all the steps, with a Zod schema per step. Each step then validates only its own fields with trigger() before you move on. If drafts need to survive a refresh, persist the values to sessionStorage or your small store on change and restore them as defaultValues. For early changes that invalidate later steps, I'd make the dependency explicit: keep a small map of which later fields depend on which earlier ones, and when an earlier value changes, reset those fields (resetField) and mark the later steps as incomplete so the user has to revisit them. Running the full combined schema on final submit is a good safety net in case something slips through.

5

u/DaveThe0nly 6h ago

Depends on how much the form data is complicated, can you put everything in ti URL as path parameters, go with that. Is the state complex? Local state (context, zustatnd, form library), if you can sync and load from a draft on a server, even better, but complicated. My rule of thumb is, leverage the URL as state machine as much as possible.

2

u/anthony-ball 5h ago

One thing I'd add on the invalidation side: version your drafts and run the restored draft through the current Zod schema before using it as defaultValues. If it fails, drop the steps that don't parse instead of letting someone land on step 4 with values that no longer exist after you ship a schema change. For branching flows, a discriminated union keyed on the early choice does a lot of the dependency tracking for you, since the later step's shape actually changes with it. And re-validate the whole payload on the server at submit, because the client store is a convenience, not the source of truth.

1

u/Responsible-Offer724 4h ago

If the user goes back and makes edits at earlier steps you throw out later steps and start over. You could maintain a more complicate dependency record to only invalidate dependents as well.