Composition & children
Compose components via the children prop and slots; favor composition over inheritance for flexible reuse.
React has no component inheritance. You reuse and customize UI by composing components—nesting them and passing content through props. This is the idiom the whole ecosystem is built on.
The children prop 🎯#
Whatever JSX you nest inside a component's tags arrives as the special children prop. This gives you containment: a component that renders a shell around arbitrary content it doesn't know in advance.
function Card({ children }) {
return <div className="card">{children}</div>;
}
<Card>
<h2>Title</h2>
<p>Any content the parent supplies.</p>
</Card>
A layout wrapping children#
flowchart TD
L["Layout (knows structure)"] --> H["header slot"]
L --> M["{children} — main content"]
L --> F["footer slot"]
P["Page (supplies content)"] -->|"passes JSX"| M
Slots: multiple named holes#
When one children isn't enough, pass JSX through named props—React elements are just values, so any prop can carry UI.
function Layout({ sidebar, children, footer }) {
return (
<div className="layout">
<aside>{sidebar}</aside>
<main>{children}</main>
<footer>{footer}</footer>
</div>
);
}
<Layout sidebar={<Nav />} footer={<Copyright />}>
<Dashboard />
</Layout>
Specialization#
Build a specific component by configuring a generic one—the composition analog of subclassing.
function Dialog({ title, children }) {
return <div className="dialog"><h1>{title}</h1>{children}</div>;
}
// WelcomeDialog "specializes" Dialog by rendering it with fixed content
function WelcomeDialog() {
return <Dialog title="Welcome">Thanks for signing up.</Dialog>;
}
Passing components as props#
Pass the component type (not an element) when the child controls its own rendering—common in render-prop and headless-component APIs.
function List({ items, renderItem }) {
return <ul>{items.map(renderItem)}</ul>;
}
<List items={users} renderItem={(u) => <li key={u.id}>{u.name}</li>} />
🟢 Composition also sidesteps prop drilling and unnecessary re-renders: if a parent passes an expensive subtree as children, that subtree is created by the grandparent and doesn't re-render when the parent's own state changes.
// <ExpensiveTree/> is created once by App; Toggler's state changes don't re-render it
<Toggler><ExpensiveTree /></Toggler>
Composition vs inheritance ⚠️#
| Composition (React way) | Inheritance | |
|---|---|---|
| Reuse UI | Nest / pass as props | ❌ not supported for components |
| Reuse logic | Custom hooks | ❌ |
| Flexibility | High—mix freely | Rigid hierarchy |
⚠️ There is essentially no good use case for component inheritance in React. If you're tempted to extends AnotherComponent, reach for composition or a custom hook instead.
Interview Q&A#
Q1. How does React handle "inheritance" between components?
It doesn't—React favors composition. You reuse and customize UI by nesting components and passing content via children or other props, and reuse logic via custom hooks.
Q2. What is the children prop?
The special prop holding whatever JSX a caller nests between a component's opening and closing tags, enabling containment—rendering a wrapper around content the component doesn't define itself.
Q3. How do you create multiple "slots" in a component?
Pass JSX through distinct named props (e.g. header, sidebar, footer) in addition to children. React elements are ordinary values, so any prop can carry renderable UI.
Q4. What is specialization in React composition?
Rendering a generic component with fixed configuration to produce a more specific one—e.g. a WelcomeDialog that renders a general Dialog with a preset title and body. It replaces subclassing.
Q5. How can passing content as children improve performance?
Content passed as children is created by the parent's parent, so it keeps its identity when the intermediate component re-renders due to its own state—the subtree is reused instead of re-rendered.