Lifting State Up
When two components need the same data, move that state to their closest common parent and pass it down as props.
Sometimes two sibling components need to share the same piece of data — a filter and a list, or two inputs that should stay in sync. Since data flows down in React (parent → child via props), the fix is to lift the state up to their closest common parent.
#The pattern
- Move the
useStateinto the common parent. - Pass the value down to children as props.
- Pass a setter (or a callback) down so children can request changes.
The parent owns the state; children become simpler, controlled by their props.
function App() {
const [query, setQuery] = useState('');
return (
<>
<SearchBox query={query} onChange={setQuery} />
<Results query={query} />
</>
);
}
function SearchBox({ query, onChange }) {
return <input value={query} onChange={e => onChange(e.target.value)} />;
}
function Results({ query }) {
return <p>Searching for: {query || '…'}</p>;
}SearchBox and Results don't hold the state — App does. When you type, SearchBox calls onChange, App updates query, and both children re-render with the new value. One source of truth, always in sync.
How high should it go?
Lift state only as high as the closest common ancestor of the components that need it — no higher. Lifting too far makes unrelated components re-render and adds prop-drilling. When many distant components need it, reach for Context instead.
Two sibling components need to share a value. Where should that state live?
Key takeaways
- Data flows down via props, so shared state belongs in a common parent.
- Pass the value down as a prop and a setter/callback down to request changes.
- Lift only to the closest common ancestor — not higher.
- For state needed by many distant components, use Context instead of deep prop-drilling.
Two siblings must share a counter. Following 'lifting state up', where should the useState live?
// <App>
// <Display /> needs to READ count
// <Controls /> needs to CHANGE countThe child can't change the parent's state. What should the parent pass down?
function App() {
const [on, setOn] = useState(false);
return <Toggle value={on} />; // child needs to flip it
}Order the steps to lift state up so two siblings can share it.
Pass a setter or callback down so a child can request a change
Move the useState into the closest common parent
A child calls the callback, the parent updates state, both children re-render
Pass the value down to each child as a prop
Two <TemperatureInput> components (Celsius and Fahrenheit) should stay in sync. Where does the shared temperature state belong, and what do the inputs receive?
Try it live — edit the code and hit Run to see it rendered: