Skip to main content

State Hoisting

State hoisting = move state up to common ancestor


What is State Hoisting?

"Lift state to shared parent"

State hoisting is moving state up to the nearest common ancestor when multiple components need the same state.

"State hoisting is the pattern of moving state from child components to a common parent when multiple components need to share that state."


Why Hoist State?

Share state between siblings

When siblings need the same state:

  • Move state to their common parent
  • Pass down as props
  • Update via callbacks

"State hoisting allows sibling components to share state by moving it to their common parent."


Example: Sibling Components

State in parent, props to children

// ❌ Before - state in child
function Child1() {
const [count, setCount] = useState(0);
return <div>{count}</div>;
}

function Child2() {
// Can't access count from Child1
}

// ✅ After - state hoisted
function Parent() {
const [count, setCount] = useState(0);
return (
<>
<Child1 count={count} />
<Child2 count={count} setCount={setCount} />
</>
);
}

"Hoist state to parent when siblings need to share it, passing down as props and callbacks."


Data Flow

State down, events up

Parent (state)
↓ props
Child1, Child2
↑ callbacks
Parent (updates state)

"State hoisting follows unidirectional data flow: state flows down via props, events flow up via callbacks."


When to Hoist

Multiple components need same state

Hoist when:

  • Siblings need same state
  • Parent needs to control child state
  • State affects multiple components
  • Need single source of truth

"Hoist state when multiple components need the same state or when you need a single source of truth."


When NOT to Hoist

Keep local if only one component needs it

Don't hoist when:

  • Only one component uses state
  • State is truly local
  • Hoisting adds unnecessary complexity

"Don't hoist state if only one component needs it - keep it local to avoid unnecessary complexity."


Callback Pattern

Pass callbacks to update state

function Parent() {
const [value, setValue] = useState("");

return <Child value={value} onChange={(newValue) => setValue(newValue)} />;
}

"Pass callbacks from parent to children to allow children to update parent state."


Multiple Levels

Hoist to nearest common ancestor

// Hoist to nearest common ancestor
function App() {
const [user, setUser] = useState(null);
return (
<Layout>
<Header user={user} />
<Content user={user} setUser={setUser} />
</Layout>
);
}

"Hoist state to the nearest common ancestor that contains all components needing the state."


9️⃣ Alternative: Context

Context for deep nesting

If hoisting goes many levels:

  • Consider Context API
  • Avoid excessive prop drilling
  • Context for widely shared state

"If hoisting requires passing props through many levels, consider Context API instead."


Best Practices

✅ Hoist to nearest common ancestor ✅ Keep state as low as possible ✅ Use callbacks for updates ✅ Consider Context for deep nesting ❌ Don't hoist unnecessarily ❌ Don't create unnecessary parent components


"State hoisting moves state from children to a common parent when multiple components need the same state. It follows unidirectional data flow - state down via props, events up via callbacks. Hoist to the nearest common ancestor. If hoisting requires many levels, consider Context API instead."


🧠 Ultra-Short Cheat Sheet

Move state to common parent
Share between siblings
State down, events up
Nearest common ancestor
Consider Context for deep nesting
Single source of truth