Children as Composition
Props can carry data such as a title or lesson count. They can also carry React content. JSX nested between a component's opening and closing tags is supplied through the prop named children.
<Panel>
<p>Read the lesson before continuing.</p>
</Panel>Panel receives the paragraph as props.children. The parent chooses the nested content. Panel chooses where that content appears inside its own structure.
This division is composition. Components are assembled through their public inputs without one component importing every possible child that can appear inside it.
Receive the children Prop
Define a wrapper.
function Panel({ children }) {
return (
<section className="panel">
{children}
</section>
);
}Use it with nested content.
<Panel>
<p>Read the lesson before continuing.</p>
</Panel>The component element conceptually receives one prop.
children -> paragraph elementWhen Panel returns {children} inside the section, React continues through that supplied paragraph element. React DOM creates the section and paragraph in the resulting host tree.
The parent creates the child content. The wrapper decides where to place it.
The wrapper does not call the paragraph as a component and does not convert it to HTML. It receives a React node value through its props object.
Nested Text Also Becomes Children
Plain nested text is supplied through children.
<Panel>Read the lesson before continuing.</Panel>Panel receives a string. React can render that string inside the returned section.
function Panel({ children }) {
return <section>{children}</section>;
}Do not assume children is always an element object. Depending on the caller, it can be text, a number, an element, several nodes, or an empty value.
TypeScript represents a prop that accepts the normal range of renderable React children with ReactNode.
Several Nested Nodes Form One Children Value
A caller can supply several sibling nodes.
<Panel>
<h2>Before you continue</h2>
<p>Save the current file.</p>
</Panel>React represents the children in the element's props. The wrapper can render them together with {children}.
Do not depend on children always being a normal array. A single child is not wrapped into an array merely for consistency, and React can use other internal representations. Treat children as opaque React content unless a component has a defined reason to transform it.
React supplies Children helpers for selected legacy and library patterns. They are not the default method for ordinary composition. Explicit data arrays are clearer when a component needs to map records, filter items, or attach IDs.
Do not call children.map without establishing that your public prop requires an actual array. Normal JSX children do not promise that method.
A Wrapper Adds Its Own Structure
Panel can add a heading while leaving the body open to the parent.
function Panel({ title, children }) {
return (
<section className="panel">
<h2>{title}</h2>
<div className="panel-body">{children}</div>
</section>
);
}The parent supplies both a data prop and nested content.
<Panel title="Chapter progress">
<LessonProgress completed={2} total={6} />
</Panel>Panel defines the outer section, heading, and body container. The parent supplies LessonProgress as the body content.
This keeps the wrapper reusable without adding a prop for every content combination.
Compare Fixed Content with Open Content
This component fixes its body.
function ProgressPanel() {
return (
<section>
<h2>Progress</h2>
<LessonProgress />
</section>
);
}It is appropriate when the component's responsibility is specifically the progress region.
This component accepts open content.
function Panel({ title, children }) {
return (
<section>
<h2>{title}</h2>
{children}
</section>
);
}It is appropriate when several page sections share the same container structure.
Neither version is universally better. Use fixed content when the feature is part of every instance. Use children when callers should choose what appears inside the wrapper.
Avoid a Prop for Every Markup Detail
A card API can become tied to one layout.
<Card
heading="Props as Inputs"
paragraph="Fourteen minutes"
buttonText="Open"
/>The component must define the exact arrangement and behavior for every field. Adding a second paragraph or a list requires more props and more internal branches.
Composition can keep the card body open.
<Card>
<h2>Props as Inputs</h2>
<p>Fourteen minutes</p>
<button type="button">Open</button>
</Card>The wrapper can remain small.
function Card({ children }) {
return <article className="card">{children}</article>;
}Do not replace every descriptive prop with children. A prop named status communicates a supported component behavior better than asking each caller to rebuild status markup. Children fit content slots. Named props fit data and behavior contracts.
Use named props for values the component interprets. Use children for nested content the component places without needing to understand every part.
Children Can Contain Components
The nested content can include host elements and custom components.
<Panel title="Lessons">
<LessonList />
<ContinueButton />
</Panel>Panel does not need imports for LessonList or ContinueButton. The parent module creates those elements and passes them in.
This lowers dependency coupling. The generic wrapper depends only on React content; the page chooses the feature components placed inside it.
The React component tree retains all component occurrences.
ChapterPage
Panel
LessonList
ContinueButtonThe DOM tree follows the host elements returned by each component.
Children Can Be Passed Explicitly
Because children is a prop, this form is valid.
<Panel children={<p>Saved</p>} />The nested form is clearer for normal composition.
<Panel>
<p>Saved</p>
</Panel>Do not supply both forms on one element. They compete for the same prop name, and the source no longer communicates which content should win.
Explicit children can be useful when props are assembled programmatically, but it should remain uncommon in handwritten component trees.
Missing Children Produce an Empty Position
Render Panel without nested content.
<Panel title="Chapter progress" />children is undefined. React renders no host content for the expression.
The section and heading still appear because Panel returns them.
function Panel({ title, children }) {
return (
<section>
<h2>{title}</h2>
{children}
</section>
);
}If a panel requires body content, make that requirement part of its public API and supply an appropriate empty result at runtime. Do not insert placeholder text at the wrapper level unless every use should display it.
Use Named Slots for Several Regions
One children position is sufficient for many wrappers. A layout with several caller-controlled regions can use named React node props.
function LessonLayout({ header, sidebar, children }) {
return (
<div className="lesson-layout">
<header>{header}</header>
<aside>{sidebar}</aside>
<main>{children}</main>
</div>
);
}The caller supplies each region.
<LessonLayout
header={<ChapterHeading />}
sidebar={<LessonNav />}
>
<LessonArticle />
</LessonLayout>header and sidebar are ordinary props holding React nodes. children fills the primary open region.
Use this pattern only when the layout genuinely exposes several caller-controlled regions. A long list of slots can make a component harder to use than direct page markup.
Do Not Mutate or Reparent Child Elements
React element values are immutable descriptions. A wrapper should render the supplied children rather than change their props object.
function Panel({ children }) {
children.props.className = "inside-panel";
return <section>{children}</section>;
}This mutation is unsupported and also fails when children is text, several nodes, or empty.
Put layout classes on the wrapper.
function Panel({ children }) {
return <section className="panel-content">{children}</section>;
}If a child needs a behavior prop, create that child with the prop at the owning parent.
<Panel>
<LessonList compact />
</Panel>This keeps the contract visible where the element is created.
Build the Chapter Page Through Composition
Create a reusable Panel.
function Panel({ title, children }) {
return (
<section className="panel">
<h2>{title}</h2>
{children}
</section>
);
}Compose the page.
<Panel title="Chapter progress">
<LessonProgress completed={2} total={6} />
</Panel>Use the same structure for another content type.
<Panel title="Continue reading">
<LessonCard title="Conditional UI" minutes={16} />
</Panel>The wrapper stays unchanged. The page retains control of the actual body content.
Lesson Check
The composition path can now be stated precisely.
the parent creates nested React nodes
JSX stores them in the children prop
React calls the wrapper with that prop
the wrapper places children in its returned tree
React continues rendering the supplied nodes thereSource Notes
- React documentation, Passing Props to a Component
- React documentation, Passing JSX as children
- React documentation, Children
- React documentation, Alternatives to manipulating children