State Colocation

⭐ Interview Importance: MEDIUM
⏱️ Revision Time: 2 min

State Colocation

State Colocation is the practice of moving React state as close as possible to where it is actually used.

It is the counter-balance to the “Lifting State Up” pattern. While lifting state up is necessary for sharing data, lifting state too high is terrible for performance and maintainability.

The Problem: Global State Abuse

A common mistake among junior developers is putting everything into a global state manager (like Redux) or keeping all state in the top-level App.js component.

// ❌ Bad: State is lifted too high
function App() {
  const [isModalOpen, setIsModalOpen] = useState(false);
  const [formInput, setFormInput] = useState('');

  return (
    <div>
      <Navbar />
      <Sidebar />
      <MainContent 
        isModalOpen={isModalOpen} 
        setModalOpen={setIsModalOpen}
        formInput={formInput}
        setFormInput={setFormInput}
      />
    </div>
  );
}

Why this is terrible:

  1. Performance: Because of React’s top-down rendering model, every time the user types a single character into the formInput, the setFormInput function is called. This updates the state in App, which forces <App />, <Navbar />, <Sidebar />, and <MainContent /> to all re-render simultaneously.
  2. Readability: The App component becomes bloated with state variables that it doesn’t actually care about.

The Solution: State Colocation

State Colocation means pushing the state down the component tree, as deep as it can possibly go, until it lives exactly next to the components that need it.

If only the <ContactForm /> needs to know what text the user is typing, the formInput state should live inside <ContactForm />, nowhere else.

If only the <DeleteButton /> needs to know if the confirmation modal is open, the isModalOpen state should live inside <DeleteButton />.

// ✅ Good: State is colocated where it is used
function ContactForm() {
  // This state is colocated. When it updates, ONLY the ContactForm re-renders.
  // The Navbar and Sidebar are completely unaffected.
  const [formInput, setFormInput] = useState('');

  return <input value={formInput} onChange={e => setFormInput(e.target.value)} />
}

The “Colocation” Philosophy

Colocation doesn’t just apply to state. It is a broader philosophy in modern React development that applies to everything:

  • “Place code as close to where it’s relevant as possible.”
  • CSS: Use CSS Modules or Styled Components to colocate styles in the same folder as the component, rather than one massive global.css file.
  • Tests: Place Button.test.js right next to Button.js.
  • Types: Define TypeScript interfaces in the same file as the component that uses them.

Colocation makes deleting and refactoring code incredibly safe. If you delete ContactForm.js, you automatically delete its state, its styles, and its tests, leaving no dead code behind.

Interview Questions

Q: What is State Colocation?
A: The practice of moving state as physically close as possible to where it is actually used. Instead of putting a modal’s isOpen boolean in a massive global Redux store, you keep it entirely local inside the component that renders the modal. This improves performance and code readability.