State Ownership in React
State ownership means deciding which component is responsible for storing a piece of mutable state and controlling how that state changes. Good ownership keeps a single source of truth while passing data downward through props and updates through explicit callbacks.
In a component-based UI, state should generally live in the closest component that needs to control it. A component that owns state is responsible for deciding when and how that state changes, while descendant components can receive the current value through props.
When multiple sibling components need the same mutable value, their common ancestor is often the appropriate owner. The ancestor stores the state and passes the relevant value to each child. If a child needs to change the value, the parent can pass a callback that represents the permitted update.
This arrangement creates a single source of truth. Instead of maintaining separate copies of the same value in different components, one component owns the authoritative value and other components derive their UI from it. This reduces synchronization problems and makes data flow easier to reason about.
State should not automatically be lifted as high as possible. Moving state upward can increase the number of components that re-render or make component interfaces more complicated. Keep state local when only one component or a small subtree needs it, and lift it when shared coordination requires a common owner.
Props and state serve different roles: props are inputs supplied by a parent, while state is data managed by the component that owns it. A child should normally communicate a requested change through an event handler or callback rather than directly modifying the parent's state.
Key points
- The state owner is the component responsible for storing and updating the value.
- Use a single source of truth when multiple components depend on the same mutable data.
- Lift shared state to the nearest common ancestor that needs to coordinate it.
- Pass state downward with props and expose permitted updates through callbacks.
- Avoid lifting state unnecessarily because it can increase coupling and rendering work.
Interview questions
How do you decide which component should own a piece of state?
Start by identifying every component that needs to read or change the value. Keep the state in the lowest common ancestor that can coordinate those requirements. If only one component needs it, local ownership is usually simpler. If siblings need it, move the state to their common parent and pass the value and update mechanism through props.
Why is a single source of truth useful?
A single source of truth means one location owns the authoritative version of a value. Other components consume that value rather than maintaining independent copies that can diverge. Updates therefore have a clear path and dependent UI can be derived consistently. This is especially useful when several components must remain synchronized.
How should a child component update state owned by its parent?
The parent can pass a callback as a prop. The child invokes that callback when a user interaction requests a change, while the parent performs the actual state update. This keeps ownership in the parent and makes the update path explicit. The child does not need direct access to the parent's state setter unless the design specifically exposes it that way.
What is the downside of lifting state too far up the component tree?
Over-lifting can make unrelated components depend on state they do not conceptually own. It can create long prop chains, increase coupling, and cause broader portions of the tree to participate in updates. The solution is not to keep all state local, but to choose an owner that matches the actual sharing boundary. For larger applications, context or an external state-management approach may sometimes provide a better distribution mechanism.
When should you avoid putting a value in React state?
A value does not need independent state if it can be reliably computed from existing props or state. Storing both the source value and its derived representation creates two pieces of data that can become inconsistent. Instead, calculate the derived value during rendering when the computation is inexpensive. State is appropriate when the value must persist independently across renders and can change due to interaction, asynchronous work, or another external event.