5 min read
0%

Lifting State Up — Trade-offs

Back to Blog
Lifting State Up — Trade-offs

Lifting State Up — Trade-offs

Lifting state means moving it to the nearest common ancestor of components that need to share it. It’s the standard React data-sharing mechanism, with real costs.

When to Lift

When two sibling components need to share or synchronize state:

// Before: each input manages its own state — can't sync
function TempConverter() {
  return (
    <>
      <CelsiusInput />
      <FahrenheitInput />
    </>
  );
}

// After: state lifted to common parent
function TempConverter() {
  const [celsius, setCelsius] = useState(0);
  const fahrenheit = celsius * 9/5 + 32;

  return (
    <>
      <CelsiusInput value={celsius} onChange={setCelsius} />
      <FahrenheitInput
        value={fahrenheit}
        onChange={f => setCelsius((f - 32) * 5/9)}
      />
    </>
  );
}

The Costs

Re-render propagation. When lifted state updates, the common ancestor and all its children re-render — including components that don’t use the state.

function Parent() {
  const [count, setCount] = useState(0);
  return (
    <>
      <HeavyComponent /> {/* re-renders every time count changes */}
      <Counter count={count} onIncrement={() => setCount(c => c + 1)} />
    </>
  );
}

Fix with React.memo on HeavyComponent, or use composition to restructure the tree.

Prop drilling. Lifted state becomes a prop that may need to pass through many layers before reaching the component that uses it.

Coupling. The parent now owns the state and must understand its children’s concerns. Tighter coupling, harder to refactor.

Alternatives to Lifting

Composition: pass components as props so the parent doesn’t re-render intermediaries.

Context: for state needed far down the tree — avoids drilling but has its own re-render costs.

URL state: for navigation-relevant state (?tab=settings). Shareable, persists on refresh.

External store (Zustand, Jotai): for state shared across multiple subtrees with minimal re-render surface.

When to Stop Lifting

Warning sign: you’re lifting state to a component that has many children who don’t use it, just to pass it to one that does. That’s when you switch to context or a store.


Canvas is not supported in your browser