Lifting state helps share data between components by moving the state up to a common parent.
Common lifting state patterns in React
import React, { useState } from 'react'; function Parent() { const [value, setValue] = useState(''); return ( <> <ChildA value={value} onChange={setValue} /> <ChildB value={value} /> </> ); } function ChildA({ value, onChange }) { return <input value={value} onChange={e => onChange(e.target.value)} />; } function ChildB({ value }) { return <p>{value}</p>; }
State is stored in the parent component.
Child components receive state and update functions as props.
import React, { useState } from 'react'; function Parent() { const [count, setCount] = useState(0); return ( <> <Incrementer count={count} onIncrement={() => setCount(count + 1)} /> <Display count={count} /> </> ); } function Incrementer({ count, onIncrement }) { return <button onClick={onIncrement}>Add 1 (current: {count})</button>; } function Display({ count }) { return <p>Count is {count}</p>; }
import React, { useState } from 'react'; function Parent() { const [text, setText] = useState(''); return ( <> <TextInput text={text} onTextChange={setText} /> <TextPreview text={text} /> </> ); } function TextInput({ text, onTextChange }) { return <input value={text} onChange={e => onTextChange(e.target.value)} />; } function TextPreview({ text }) { return <p>You typed: {text}</p>; }
This example shows lifting state to a parent to share the typed name between input and greeting.
The input updates the parent's state, and the greeting updates automatically.
import React, { useState } from 'react'; export default function Parent() { const [name, setName] = useState(''); return ( <main> <NameInput name={name} onNameChange={setName} /> <Greeting name={name} /> </main> ); } function NameInput({ name, onNameChange }) { return ( <label htmlFor="nameInput"> Enter your name: <input id="nameInput" type="text" value={name} onChange={e => onNameChange(e.target.value)} aria-label="Name input" /> </label> ); } function Greeting({ name }) { return <p>{name ? `Hello, ${name}!` : 'Please enter your name above.'}</p>; }
Always keep state as high as needed but no higher to avoid unnecessary re-renders.
Use clear prop names like onChange or onNameChange for callbacks.
Remember to pass both the state value and the setter function down to children.
Lifting state means moving state up to a common parent to share it.
Child components get state and update functions as props.
This helps keep data in sync across components.
Practice
lifting state means moving state to a common parent component.Solution
Step 1: Understand lifting state concept
Lifting state means moving state to a common parent so multiple children can access it.Step 2: Identify the purpose of lifting state
This is done to share state between sibling components and keep data in sync.Final Answer:
To share state between sibling components -> Option BQuick Check:
Lifting state = sharing state [OK]
- Thinking lifting state makes components independent
- Believing lifting state removes props usage
- Assuming state stays only in children
Solution
Step 1: Recall React props syntax
Props are passed asname={value}. To pass state and updater, usestate={state}andsetState={setState}.Step 2: Check each option's syntax
<Child state={state} setState={setState} />correctly passes both as props. Others misuse assignment or call functions incorrectly.Final Answer:
<Child state={state} setState={setState} /> -> Option AQuick Check:
Props pass state and updater correctly [OK]
- Passing functions without curly braces
- Calling updater functions instead of passing them
- Swapping state and updater names
function Parent() {
const [count, setCount] = React.useState(0);
return (
<>
<Display count={count} />
<Button onClick={() => setCount(count + 1)} />
</>
);
}What will happen when the Button is clicked?
Solution
Step 1: Understand state and props flow
The Parent holds count state and passes count to Display and an onClick handler to Button.Step 2: Analyze Button click effect
Clicking Button calls setCount(count + 1), updating state and causing Parent to re-render with new count.Final Answer:
The count displayed by Display increases by 1 -> Option CQuick Check:
State update triggers re-render and display update [OK]
- Thinking Button needs count prop to update
- Believing setCount must be passed to Display
- Assuming no re-render happens on state change
function Parent() {
const [value, setValue] = React.useState('');
return <Child value={value} setValue={value} />;
}Solution
Step 1: Check props passed to Child
Parent passesvalue={value}correctly butsetValue={value}incorrectly passes the state value instead of the updater function.Step 2: Understand correct usage
setValue should be passed assetValue={setValue}to allow Child to update state.Final Answer:
setValue prop is incorrectly assigned the state value instead of the updater function -> Option AQuick Check:
Updater function must be passed, not state value [OK]
- Confusing state variable with updater function
- Forgetting curly braces around variables
- Assuming React.useState is incorrect
InputA and InputB, both need to update and display the same text value. Which pattern correctly lifts state to their parent to keep them in sync?Solution
Step 1: Understand shared state need
Both siblings must show and update the same text, so state must be shared.Step 2: Apply lifting state pattern
Lift text state to their common parent and pass text and setText as props to both siblings.Step 3: Evaluate other options
Storing state separately or in one sibling breaks sync; local variables don't persist or trigger re-renders.Final Answer:
Store text state in parent, pass text and setText to both siblings as props -> Option DQuick Check:
Lift state to parent for shared updates [OK]
- Keeping separate states in siblings causing out-of-sync
- Passing state only one way between siblings
- Using local variables instead of state
Ready to prove it?
Pass the test and this pattern moves unknown
