What does "state colocation" do?
What is state colocation
State colocation is the principle:
"Keep state as close as possible to where it is used."
That is: if state is needed only by one component - do not lift it "up" to the parent, but keep it right in the component where it is actually used.
Example without colocation (bad)
function App() {
const [isOpen, setIsOpen] = useState(false); // stored too high up
return (
<div>
<Header />
<Modal isOpen={isOpen} setIsOpen={setIsOpen} />
<Footer />
</div>
);
}Here isOpen affects only Modal,
but it is stored in App and passed down through props.
→ This complicates the App component,
and causes unnecessary re-renders when the state changes.
With colocation (correct)
function Modal() {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<button onClick={() => setIsOpen(true)}>Open</button>
{isOpen && <div className="modal">Modal!</div>}
</>
);
}Now the state lives where it is actually used.
The App component no longer knows anything about Modal's internal logic.
Why this matters
1. Less coupling
When state lives "up top", it starts to:
- get passed through
propsacross several levels, - cause "prop drilling" (passing props through a chain of components),
- complicate the parent's logic.
Colocation removes this - each component is responsible only for itself.
2. Fewer unnecessary re-renders
If state is stored too high up, all child components re-render, even if they do not depend on it.
When state is localized, only the component that needs it reacts to the update.
This improves performance.
3. The code is easier to understand
A component is easier to read when:
- its state is visible in the same file,
- it is visible which UI elements that state controls.
You do not need to jump between files to understand who manages what.
4. Easier to scale
As a project grows, "global" state turns into chaos. Colocation makes the architecture modular:
- components can be reused independently,
- state does not "leak" outward.
Example of the impact on performance
Without colocation
function App() {
const [selectedId, setSelectedId] = useState(null);
return (
<div>
<List selectedId={selectedId} setSelectedId={setSelectedId} />
<Details id={selectedId} />
</div>
);
}Now every click in the list → re-render of App, List, and Details.
With colocation (partially moved down)
function List({ onSelect }) {
const [selectedId, setSelectedId] = useState(null);
const handleClick = (id) => {
setSelectedId(id);
onSelect(id);
};
// ...
}Now a click only updates List,
and App is not touched at all.
When you do not need to localize state
Sometimes the opposite is true - state needs to be lifted up, if:
- it affects several components (shared state);
- synchronization between parts of the UI is required;
- or global management is needed (via Context, Redux, Zustand, etc.).
Example:
// the selected theme is needed by all components
const [theme, setTheme] = useState("dark");Summary
| Principle | What it means |
|---|---|
| State colocation | Keep state as close as possible to where it is used |
| Why | Reduces coupling, improves performance, simplifies the code |
| When to apply | When state is used in only one component |
| When not to apply | When state needs to be shared between several components |
| Main goal | Minimize the state's "area of influence" |
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.