The Problem: Two Components Need the Same State
If two sibling components both need access to the same piece of state, keeping that state inside just one of them means the other has no way to read or update it — since props only flow downward.
The Solution: Move State to the Common Parent
"Lifting state up" means moving the shared state to the closest common ancestor of the components that need it, then passing it back down as props — along with a callback for children to request changes.
State Lifted to the Parent
function TemperatureConverter() {
const [celsius, setCelsius] = useState("");
return (
<>
<TemperatureInput value={celsius} onChange={setCelsius} />
<TemperatureDisplay celsius={celsius} />
</>
);
}
function TemperatureInput({ value, onChange }) {
return <input value={value} onChange={(e) => onChange(e.target.value)} />;
}
function TemperatureDisplay({ celsius }) {
const fahrenheit = celsius ? (celsius * 9) / 5 + 32 : "";
return <p>{fahrenheit}°F</p>;
}The General Pattern
This is one of the most common patterns in React: data flows down as props, and a callback prop lets a child request a change, which the parent handles by updating its own state — triggering a re-render that flows the new value back down.
Steps to Lift State Up
- Identify which components need to share the same state.
- Find their closest common parent component.
- Move the state (useState) into that parent.
- Pass the state value down as a prop to each child that reads it.
- Pass a callback function down as a prop to each child that needs to update it.
When Lifting Gets Awkward
If the shared state needs to reach components many levels apart, lifting it all the way up can mean threading props through several components that don’t use it — a sign it might be time to reach for the Context API instead, covered next.
Best Practice
Keep state as close as possible to where it’s used — only lift it up to the smallest common ancestor actually needed, not all the way to the top of the app "just in case."