Prefer multiple useState or useReducer for multi-field forms?

Matching state structure to complexity.
Separate useState for simple fields; one object for coupled validation or batch resets; useReducer for complex logic.
Picking one pattern for all forms without discussing coupling.
WHAT THIS TESTS: This question tests whether you can match state architecture to actual UI complexity rather than relying on habit. Interviewers want to see that you understand the trade-offs between colocation, readability, and predictable updates. The core signal is your ability to explain when useState becomes a liability and why useReducer adds value beyond syntax preference.
A GOOD ANSWER COVERS: A strong answer presents a clear escalation ladder. First, for two or three independent fields like a search box and a toggle, separate useState hooks are fine because each setter is isolated and the logic stays trivial. Second, when fields are related, such as a shipping form where city, state, and zip must validate together or reset as a unit, a single state object reduces stale state bugs and makes batch updates atomic. Third, when the form grows interdependent logic, like a multi-step wizard where selecting a country changes available provinces, enables VAT fields, and triggers async tax lookups, useReducer becomes the better tool because it centralizes transition logic into a pure reducer function. The dispatch function from useReducer has a stable identity, which helps when passing it into effects or callbacks without dependency headaches. You should also mention that useReducer does not inherently improve performance; it improves predictability.
COMMON WRONG ANSWERS: A red flag is insisting that useReducer is always superior for forms because it is more advanced or performant. Another mistake is claiming that multiple useState hooks cause extra re-renders compared to a single object; in React, state updates still trigger a re-render of the component regardless of how many hooks you have. Some candidates also forget to discuss the initializer function or lazy initialization with useReducer, which matters when deriving initial state from props or computing expensive defaults. Finally, avoid suggesting useReducer for a two-field login form unless you can articulate a specific reason, like shared validation logic or action replay.
LIKELY FOLLOW-UPS: An interviewer might ask how you would handle derived state, such as whether a total price should live in reducer state or be computed during render. They may also probe how you would reset the form to its initial state, which is cleaner with useReducer because you can dispatch a RESET action or reinitialize. Another common follow-up is how you would persist draft state to localStorage; here, a reducer can centralize side-effect coordination or you might reach for a custom hook. You might also be asked how React Hook Form or similar libraries change the equation.
ONE CONCRETE EXAMPLE: Imagine a checkout form with email, shipping address, and billing address fields, plus a checkbox for same-as-shipping. With separate useState hooks, checking the box would require manually copying shipping values into billing and keeping them in sync, which is fragile. With a single object and useReducer, you dispatch a SYNC_BILLING action that derives the next billing state from the current shipping state inside the reducer, making the relationship explicit and testable. If the user later unchecks the box, the reducer can restore the previously independent billing values or clear them based on a single action type.
Source: react.dev
Read the original → react.dev
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.