When to Use One State Object vs Multiple useState Hooks

Use one state object for values that change together and multiple useState hooks for values that change independently. See the deciding rule.

5 min read

The choice between one state object vs multiple useState hooks depends on how often the values change together. Group values that move as a unit, and keep independent values in separate hooks. The goal is to make each update easy to get right.

The decision is rarely about saving lines. It is about how often two values must move together, because that determines how much each update has to remember.

The deciding question

Ask whether the values always change at the same time. The answer picks the structure for you.

SituationPrefer
Values always change togetherOne object
Values change independentlySeparate hooks
A value is derived from othersNo state, compute it

This single question catches most mistakes. When two values must stay in sync, splitting them means every update has to remember both. Grouping them makes one update do both.

The exception is a form with an unknown number of fields, where one object or array scales more naturally than a fixed set of hooks.

Group values that change together

A cursor position has an x and a y that move as one. A single object keeps them from drifting apart.

App.jsxApp.jsx
const [position, setPosition] = useState({ x: 0, y: 0 });
 
function handleMove(x, y) {
  setPosition({ x, y });
}

Moving the pointer sets both coordinates in one call. There is no way to update x and forget y, because they live in the same object and are replaced together. Form fields for one address group the same way, because a full address usually changes as a unit.

Grouping into an object means you must copy the fields you are not changing. Updating objects in state shows the spread pattern for that.

Split values that change independently

A first name and a last name are edited by different inputs at different times. Two hooks keep them simple.

App.jsxApp.jsx
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");

Each input updates only its own value, and neither update has to copy the other field. If these were one object, every keystroke would need the spread just to keep the other name intact. Separate hooks also make each handler trivial, since there is nothing to copy.

The same rule applies to a form with many fields. Fields that a user fills in separately are usually independent, so separate hooks, or a dedicated form library, read more clearly than one giant object. The moment two fields must move together, that pair belongs in one object.

Avoid impossible and redundant state

Structure also prevents contradictory values. Two booleans like isSending and isSent can never both be true, so a single status value is safer. Two booleans allow the impossible state where both are true at once, and every update must remember to clear the other.

  • Values that can contradict: combine them into one.
  • Values computed from others: do not store them.
  • Duplicated data: keep one copy and derive the rest.

A full name is computed from first and last during render, so it should not be its own state variable. The derived state guide covers that in detail.

Avoid deeply nested state

Deeply hierarchical state is painful to update, because changing a leaf means copying every object above it. Prefer a flatter shape.

A list of places nested inside planets inside a root forces you to spread several levels for one edit. Storing each place by id in a flat map turns the same edit into a single-level copy, which is far easier to write.

What to learn next

Once the structure is right, updates become small and predictable. See useState in action for the fundamentals, then resetting state when you need to start over.

Rune AI

Rune AI

Key Insights

  • Group values that always change together.
  • Split values that change independently.
  • Update an object field with the spread syntax.
  • Do not store values you can derive during render.
  • Avoid state that can become contradictory.
RunePowered by Rune AI

Frequently Asked Questions

Should I always group state into one object?

No. Group values only when they always change together. Independent values are easier as separate hooks.

What happens if I forget to copy a field when updating an object?

The new object loses that field. The spread syntax copies the old fields first, then your override wins.

Is a derived value state?

No. If you can compute a value from existing props or state during render, compute it instead of storing it.

Conclusion

Group values that always change together into one object, and keep independent values in separate hooks. Compute derived values during render instead of storing them.