- Home
- /
- Tutorials
- /
- React Tutorial
- /
- Children and Composition
Components and Props
Children and Composition
Anything between a component's opening and closing tags arrives as
props.children. It is the difference between a component that configures content and one that wraps it.
The children prop
children is an ordinary prop with a special source: JSX fills it from whatever sits between the tags. That is what lets a component act as a container without knowing what it contains.
A wrapper that knows nothing
jsx
function Panel({ title, children }) {
return (
<section style={{ border: "1px solid #cbd5e1", borderRadius: 10, padding: 14 }}>
<h4 style={{ margin: "0 0 8px" }}>{title}</h4>
{children}
</section>
)
}
const root = ReactDOM.createRoot(document.getElementById("root"))
root.render(
<div style={{ display: "grid", gap: 12 }}>
<Panel title="Text inside">
<p>Just a paragraph.</p>
</Panel>
<Panel title="Anything else inside">
<ul>
<li>A list</li>
<li>works too</li>
</ul>
<button>And a button</button>
</Panel>
</div>
)Panel handles the frame and the heading. What goes inside is entirely the caller's business, which is why one Panel serves both examples without a single option.
Children or a prop?
Both pass content down, so the choice is about who should decide the markup.
- Use a prop for a value the component will format itself - a title, a count, a date.
- Use children for arbitrary content the component only positions.
- If you find yourself passing JSX as a normal prop, children is usually what you wanted.
More than one slot
A component only has one children, but JSX elements are values - so a second region is just another prop that happens to hold JSX.
Two slots
jsx
function SplitPanel({ left, children }) {
return (
<div style={{ display: "flex", gap: 12, border: "1px solid #cbd5e1", borderRadius: 10, padding: 12 }}>
<div style={{ width: 90, color: "#475569" }}>{left}</div>
<div style={{ flex: 1 }}>{children}</div>
</div>
)
}
const root = ReactDOM.createRoot(document.getElementById("root"))
root.render(
<SplitPanel left={<strong>Label</strong>}>
<p style={{ margin: 0 }}>The main region arrives as children.</p>
</SplitPanel>
)Why this matters later
Composition through children is how React avoids most of the problems other systems solve with inheritance or configuration. A layout does not need options for every possible content - it takes children and gets out of the way.
It is also the usual answer to "how do I avoid passing this prop through four levels". Often you can pass the finished element down instead of the data it needs, and the middle layers stop caring.
