Lifting state & composition patterns
Single source of truth, controlled components, children and slots, compound components and render props.
React data flows one way: from parents down to children through props. That raises two everyday questions: where should a piece of state live? and how do I structure components so they're flexible and reusable? This lesson answers both with two core skills — lifting state up and composition.
Lifting state up#
Imagine an FAQ where only one panel may be open at a time. If each Panel owns its own isOpen state, they can't coordinate:
The fix: move the state up to their common parent and pass it down:
The recipe:
- Remove the state from the children.
- Pass the values down as props (
isActive). - Pass event handlers down so children can ask the parent to change it (
onShow).
Panel is now a controlled component — its parent decides what it shows. It's also simpler and easier to test.
A single source of truth#
For each piece of state, pick one component that owns it. Find it like this:
- List every component that reads or changes the state.
- Find their closest common parent.
- Put the state there (or higher, if it makes more sense).
A classic example: a temperature converter where two inputs edit the same value.
Fahrenheit isn't stored at all — it's derived during render. Storing both would let them drift out of sync.
Tip: if a value can be calculated from props or other state, don't put it in state. Derive it.
Composition with children#
Components can accept JSX as props. The most common is children — whatever you nest inside the tags:
Card doesn't know or care what's inside it. This makes it reusable for profiles, lessons, settings — anything.
Multiple "slots"#
Any prop can hold JSX, so you can create several slots:
Composition beats prop drilling#
Prop drilling is passing props through components that don't use them, just to reach a deep child:
Before reaching for context, try composition — let the parent build the deep element and pass it as JSX:
Now Page and Header know nothing about user. When many distant components need the same data (theme, current user, language), that's when context earns its place.
Specialisation#
Build specific components by configuring general ones:
React doesn't use inheritance between components — composition covers every case.
Compound components#
Some components are made of parts that work together, like <select> and <option>. Compound components share state between a parent and its parts through context, so callers can arrange the parts freely:
The caller never touches the active state, yet every part stays in sync. Component libraries such as Radix UI use this pattern.
Render props (passing a function)#
Sometimes a parent needs to give the child data to render with. Pass a function:
Today, custom hooks (useMousePosition()) usually replace render props, but you'll still see the pattern in libraries like form and table components.
Keeping or resetting state#
React keeps state as long as the component stays at the same position in the tree. Two useful consequences:
Giving a component a key that changes is the cleanest way to reset its state — for example, clearing a draft message when switching contacts.
Never define components inside components#
Always declare components at the top level of a module.
Common mistakes#
- Duplicating the same state in two components and trying to keep them in sync with effects.
- Storing derived values (totals, filtered lists, the "other" temperature) in state.
- Drilling props through five layers instead of using composition or context.
- Defining components inside other components.
- Mirroring a prop into state (
useState(props.value)) and expecting it to update when the prop changes.
What's next#
Your components are well structured — now let's make them look good. Next up: styling React apps.
Check your understanding
Quick quiz
1.Two sibling components need to show and change the same value. Where should the state live?
2.What is the
childrenprop?3.Which is usually the best first fix for prop drilling through one or two layers?
Finished reading?
Mark this lesson complete to track your progress.