React has no built-in class inheritance between components, and it doesn't need one ā composition, combining simple components into more complex ones, is the idiomatic way to reuse and structure UI. This lesson covers the children prop, multi-slot patterns, containment versus specialization, and how composition avoids prop drilling.
1Composition Over Inheritance
Unlike some UI frameworks, React does not provide a way for one component to inherit from another. Instead, React is built around composition: complex components are assembled by combining simpler components, in the same way a sentence is built from words rather than inherited from another sentence.
2The children Prop as a Slot
Any JSX nested between a component's opening and closing tags is automatically passed to that component as props.children. This gives components like Card or Dialog a way to define shared layout and styling while remaining completely agnostic about the actual content they wrap.
3Multiple Slots with Named Props
While children covers a single content slot, a component can accept multiple independent JSX 'slots' by passing rendered elements as regular named props, such as a left and right prop on a SplitPane component. Each named prop can hold its own separate JSX subtree.
4Containment vs. Specialization
Containment describes components like Card or Dialog that don't know their children ahead of time and simply render whatever is passed to them. Specialization describes a more specific component expressed as a particular case of a more general one, such as a WelcomeDialog that internally renders a Dialog with fixed props ā composing rather than inheriting.
5Composition Avoids Prop Drilling
Beyond flexibility, composition is a practical tool against prop drilling: instead of threading a prop through several intermediate components that never actually use it, an already-rendered piece of JSX can be passed down from a higher level in the tree, so those intermediate components never need to know the prop exists at all.
6Step-by-Step Breakdown
Composition Over Inheritance. React has no concept of class inheritance between components ā and it doesn't need one. Instead of building a SpecialButton extends Button, React encourages composition: building complex components by combining simpler ones, the same way you assemble a sentence from words instead of inheriting one sentence from another.
The children Prop as a Slot. The children prop is React's built-in composition mechanism: whatever you put between a component's opening and closing tags is passed to it as props.children. This lets a component like Card define layout and styling while remaining completely agnostic about what content it wraps.
A Card component renders {children} inside a styled <div>. What determines what actually appears inside the card?
- āWhatever JSX is nested between <Card> and </Card>
- āFixed content hardcoded inside the Card component
Multiple 'Slots' with Named Props. children covers a single slot, but a component can accept several JSX 'slots' at once by passing elements as regular named props. A SplitPane component might accept a left prop and a right prop, each holding its own tree of JSX, giving you multiple independent injection points.
Containment vs. Specialization. There are two composition patterns: containment, where a component like Card or Dialog doesn't know its children ahead of time, and specialization, where a more specific component is expressed as a special case of a general one ā for example, WelcomeDialog renders <Dialog title="Welcome"> internally, composing rather than inheriting from it.
A WelcomeDialog component internally renders <Dialog title="Welcome" /> instead of extending a Dialog class. What pattern is this?
- āSpecialization ā a specific component composed from a general one
- āClass inheritance
Composition Avoids Prop Drilling. Composition isn't just about JSX flexibility ā it's also a tool against prop drilling. Instead of threading a prop through several layers of components that don't use it themselves, you can pass the already-rendered JSX down from a higher level, so intermediate components never need to know about that prop at all.
Mastery Achieved. You now understand React's composition model: combining components instead of inheriting from them, using children and named JSX props as flexible slots, the difference between containment and specialization, and how composition sidesteps prop drilling. This foundation sets you up for the deeper patterns ā compound components, render props, and slots ā covered later in Advanced Component Patterns.
Level Up š
Advanced cheat sheets, SEO tricks, and interview prep for this topic.
Browser Support
Fully supported.
Fully supported.
Fully supported.
Fully supported.
Accessibility (A11y)
1Containment Components Shouldn't Assume Content Semantics
A generic wrapper like Card should avoid imposing heading levels or landmark roles on its children, since it doesn't know what content will be nested inside it ā let the content passed via children define its own correct semantics.
SEO Implications
- 1
Composition Keeps Server/Client Boundaries Clean
Passing pre-rendered Server Component output down as a prop into a Client Component (composition) is the standard way to keep server-rendered content inside an interactive wrapper without forcing the whole subtree to become client-rendered.
Best Practices
Default to children for Single-Slot Wrappers
If a component only ever needs one area of injected content, prefer the children prop over inventing a custom prop name ā it matches the JSX-nesting mental model developers already expect.
Use Named JSX Props When You Need More Than One Slot
Reach for named props holding JSX (like left/right, header/footer) only when a component genuinely needs multiple independent content areas ā for a single slot, children remains clearer.
Frequent Bugs
A wrapper component renders blank even though JSX was nested inside its tags.
The component isn't rendering {children} anywhere in its return statement. Any component accepting nested JSX must explicitly destructure and render the children prop.
A prop is threaded through three components that never use it themselves, just to reach a deeply nested one.
This is classic prop drilling and is a strong signal to use composition instead ā render the deeply nested component higher up and pass the already-built JSX down as a prop, skipping the intermediate layers entirely.
Real-World Examples
A Reusable Modal Built with Containment
A Modal component renders a backdrop, a close button, and {children}, with zero knowledge of what content it will display. Different call sites pass entirely different JSX ā a confirmation message, a form, an image gallery ā and the Modal component itself never needs to change.
function Modal({ onClose, children }) {
return (
<div className="backdrop">
<div className="modal">
<button onClick={onClose}>Ć</button>
{children}
</div>
</div>
);
}