Topic 2.5
The children Prop and Composition
In one line
Whatever you write between a component's opening and closing tags arrives as the children prop, so a component can wrap content it knows nothing about; extra props that hold JSX give it more named slots, and building screens by nesting such pieces (composition) beats piling up configuration props.
Think of it like this
A gift box. The box decides the shape, the colour and the ribbon, but it doesn't care what you put inside: a book, a toy or a cake. **A wrapper component is the box and children is whatever you put in it.** The same Card box can hold a photo, a form or a list.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- children
- The prop that holds whatever you put between a component's opening and closing tags.
- Wrapper component
- A component that draws a frame (border, layout, title) around content it receives as children.
- Layout component
- A wrapper that arranges several areas of a page, such as header, sidebar and main.
- Slot
- A place in a component's JSX that the parent fills, through
childrenor a prop holding JSX. - Composition
- Building UI by nesting small components inside each other instead of configuring one big one.
- Configuration props
- Props that switch features on or off (
showIcon,variant). Good for small fixed choices. - Prop drilling
- Passing a prop down through components that don't use it, only to reach a deeper one.
- Opaque
- Something you pass along or show without looking inside it. Treat
childrenthis way.
Step by step
01Repeated frames around different content
Your page has three boxes with the same border and padding, but different things inside: a profile, a list, a form. Copying the div and its classes three times is the repeated-JSX smell from Topic 2.1, except the inside differs.
02Make the frame a component with a hole
Write Card and put {children} where the content goes. The Card doesn't know or care what that content is.
function Card({ children }) {
return <div className="card">{children}</div>;
}03Fill the hole from the parent
Write content between <Card> and </Card>. React passes it in as children.
<Card>
<h2>Asha</h2>
<p>Learning React</p>
</Card>
<Card>
<ul><li>Props</li><li>Children</li></ul>
</Card>04Add named slots
A page layout needs a header, a sidebar and a main area. children fills the main area; header and sidebar are props holding JSX.
function Layout({ header, sidebar, children }) {
return (
<div className="layout">
<header>{header}</header>
<aside>{sidebar}</aside>
<main>{children}</main>
</div>
);
}
<Layout header={<h1>Hectal</h1>} sidebar={<nav>…</nav>}>
<p>Welcome!</p>
</Layout>05Prefer composing over switches
When a component starts growing props like showIcon, iconType, showFooter, footerText, stop and ask: could the parent simply pass the icon or the footer as JSX? Usually yes, and the component gets smaller.
Try it yourself
- 1
Put a Card inside a Card
In the first example, put a
<Card title="Inner">inside the Profile card. Predict how it looks. Wrappers compose freely becausechildrencan be any JSX, including more wrappers. - 2
Predict the kind
In "What children can be", add
<Show name="G">{null}</Show>and<Show name="H">{["x", "y", "z"]}</Show>. Predict both console lines first. (G: object, becausetypeof nullis"object", andH: an array of 3.) - 3
Add a footer slot
In the layout example, pass
footer={<small>© 2026 Hectal</small>}. Then remove thesidebarprop and watch the grid adapt.
Code & diagrams
One `Card` frame, three different contents. `title` is a configuration prop; `children` is the open slot. The `&&` hides the heading when no title is passed (Topic 3.1).
Preview
Console
Nothing logged yet.Empty tags give `undefined`; one piece of text a string; one element an object; several pieces (even text plus an expression, as in E) an array. `{children}` renders all of them, so you rarely need to check.
Preview
Console
Nothing logged yet.Expected console output
A: nothing
B: string
C: object
D: an array of 2
E: an array of 2
F: number`Layout` owns the grid; the parent decides what goes in each area. Leave out `sidebar` and the aside disappears; leave out `footer` and a default text appears. Clicking a menu link is handled inside the preview.
Preview
Console
Nothing logged yet.// Configuration: every new need is another prop and another if inside Alert
<Alert
type="warning"
showIcon
title="Low storage"
showAction
actionText="Free up space"
onAction={cleanUp}
/>
// Composition: Alert is a frame, the parent arranges the pieces
<Alert type="warning">
<WarningIcon />
<AlertTitle>Low storage</AlertTitle>
<p>Only 200 MB left.</p>
<Button onClick={cleanUp}>Free up space</Button>
</Alert>Break it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Forget to render children
In the first example, change Card so it returns <section className="card">{title && <h2>{title}</h2>}</section> (no {children}).
Break #2
Give a self-closing tag content
Write <Card title="Today" children={<p>Hi</p>}>Bye</Card>.
Myth vs fact
Myth
children is a special React feature that works differently from other props.
Fact
It's an ordinary prop. JSX just fills it from whatever sits between the tags.
Myth
children is always an array.
Fact
It can be undefined, a string, a number, one element or an array. Render it with {children} and don't assume its shape.
Myth
A component can have only one slot.
Fact
Any prop can hold JSX. children is the main slot by convention; header, footer, icon and actions props make more.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
Elements passed as
childrenare created by the parent's render. If the wrapper re-renders because of its own state,childrenis the same element object as before, so React can skip re-rendering that subtree. "Lift content up, push state down" is a free performance pattern (Topic 16.1). - ▸
The
ChildrenAPI (Children.map,Children.count,Children.toArray) andcloneElementstill exist but React's docs list them as legacy: they make components fragile because they depend on the exact structure the caller writes. Prefer explicit props, context (Phase 9) or render props. - ▸
A render prop is a slot that is a function:
<List items={x} renderItem={(item) => <Row item={item} />} />. It lets the parent decide how each item looks while the child controls when and with what data it's called. Hooks replaced most render-prop uses, but it's still a clean API for customisable lists. - ▸
Composition is how libraries like Radix UI and Headless UI build accessible components:
<Dialog.Root><Dialog.Trigger /><Dialog.Content>…(compound components, Topic 22.2). The library handles ARIA and keyboard behaviour; you arrange the pieces.
Remember this
- 1
Anything placed between the tags of a component,
<Card>…</Card>, is passed to it as a prop named **children**. The component decides where to show it by writing{children}in its JSX.<Card><p>Hi</p></Card>givesCardthe props{ children: <p>Hi</p> }. It's an ordinary prop with a special way of writing it; you could even write<Card children={<p>Hi</p>} />, but nobody does. - 2
childrencan be anything that can be rendered: nothing (undefinedwhen the tags are empty or self-closing), a string, a number, one element (an object), or an array when there are several pieces side by side. Treat it as an opaque value: put it on the screen with{children}, and don't rely on its exact shape. (TheChildrenhelper API,Children.mapand friends, exists but is legacy and rarely needed.) - 3
Components that mostly provide a frame for
childrenare called wrapper or layout components:Card,Panel,Modal,PageLayout,Sidebar. They own the look (borders, spacing, grid) and leave the content to whoever uses them. Think ofchildrenas a slot: a hole in the component's JSX that the parent fills. - 4
When a component needs several slots, pass extra JSX through ordinary props:
<Layout header={<Logo />} sidebar={<Menu />}>Main content</Layout>.childrenis usually the main slot; named props such asheader,footer,actionsoriconare the others. Each one can be left empty, so the layout adapts. - 5
Composition over configuration. Instead of one component with many switches (
<Dialog showIcon iconType="warning" showCancel cancelText="No" titleBold>), make small pieces and let the parent compose them:<Dialog><DialogTitle>…</DialogTitle><WarningIcon />…</Dialog>. Every new need becomes new JSX, not a new prop and anotherif. Configuration props are still right for small, closed choices (variant="danger"); composition is better for open-ended content. - 6
Composition also helps data flow. A parent can render
<Panel><UserMenu user={user} /></Panel>:usergoes straight toUserMenu, andPanelnever needs to receive or pass it on. This avoids prop drilling (passing a prop through many components that don't use it), which you'll meet again with context in Phase 9. And because the children were created by the parent, a wrapper re-rendering on its own doesn't re-create them, a detail Phase 16 uses for performance.
Explain it without notes
What is the children prop and how is it filled?
How do you build a component with more than one slot?
What does "composition over configuration" mean? Give an example.
How can composition help you avoid prop drilling?
Practice
Write a Box wrapper that renders its children inside a div with a coloured border whose colour comes from a color prop (default "teal").
Write a Split layout with left and right slot props that shows them side by side, and use it with a list on the left and a paragraph on the right.
Trade-offs
- ↔
Composition gives callers freedom, but they must assemble more pieces themselves and can assemble them wrongly; a configured component is quicker to use for the common case. Many design systems offer both: a simple configured component built from composable parts.
- ↔
Slot props are explicit and flexible, but a component with many of them is hard to read at the call site. If you need more than three or four, consider compound components (Topic 22.2).
Done when you can
I can write a wrapper component that renders
children.I know the shapes
childrencan take and treat it as opaque.I can build a layout with several named slots.
I can explain composition over configuration with an example.
I can use composition to avoid passing props through middle components.