Component Composition

Course 1 · Ch 9
Component Composition and children
Building flexible wrapper components that don't need to know what's inside them

Every component so far has rendered its own fixed JSX. Composition is about building components that wrap other JSX without needing to know what that content actually is — a generic "Card" or "Modal" that works regardless of what's placed inside it. React's mechanism for this is a special prop every component automatically receives: children.

The children Prop

function Card({ children }) { return <div className="card">{children}</div>; } // usage <Card> <h2>Hello!</h2> <p>This content was passed in from outside.</p> </Card>

Anything written between a component's opening and closing tags — instead of using the self-closing /> form seen in every example up to now — becomes available inside that component as props.children. Card doesn't know or care that it's rendering an <h2> and a <p> specifically; it just places whatever children turned out to be inside its own wrapper <div>.

Why This Matters — Reusability Without Duplication

<Card> <h2>Profile</h2> <p>Name: Philip</p> </Card> <Card> <img src="/photo.jpg" /> <p>A completely different kind of content</p> </Card>

The same Card component now wraps two entirely different pieces of content, with zero changes needed to Card itself. Compare this to the alternative — a ProfileCard and an ImageCard, each duplicating the same wrapper markup with only the inner content differing. Composition keeps the wrapper logic written exactly once.

Combining children with Regular Props

function Panel({ title, children }) { return ( <div className="panel"> <h3>{title}</h3> <div className="panel-body">{children}</div> </div> ); } // usage <Panel title="Settings"> <p>Your preferences go here.</p> </Panel>

children works alongside any other prop, not instead of them — title is a regular named prop controlling one specific, known piece of the layout (a heading), while children handles the arbitrary, unknown part (the body content). This combination — a few named "slot" props for the structured bits, plus children for everything else — covers the vast majority of real wrapper components.

Passing More Than One "Slot" of JSX

function SplitLayout({ left, right }) { return ( <div className="split"> <div className="left">{left}</div> <div className="right">{right}</div> </div> ); } // usage — JSX passed as ordinary props, not just as children <SplitLayout left={<p>Sidebar content</p>} right={<p>Main content</p>} />

children only covers the single block of content between a component's tags — when a layout genuinely needs two or more independent regions, JSX can be passed as the value of any prop, exactly like a string or number. left={<p>...</p>} works because JSX is just a JavaScript value under the hood (from Chapter 1), and any JavaScript value can be passed as a prop.

Composition over configuration
A common instinct coming from other tools is to add more and more props to control every detail of a component's internals (showIcon, iconPosition, iconColor...). Composition often leads to a cleaner result instead — give the wrapper a flexible children slot, and let the caller render exactly the icon/markup it wants directly inside, rather than trying to anticipate every combination through props.
PatternUse it when...
childrenOne flexible region of arbitrary content
Named JSX prop (left, header, etc.)Two or more independent regions in a fixed layout
Regular prop (title, color, etc.)A single specific, known value — not arbitrary JSX

Coding Challenges

Challenge 1

Build a Box component that renders its children inside a div with a border style, then use it three times in App wrapping three completely different pieces of content (a heading, a list, a paragraph).

📄 View solution
Challenge 2

Build an Alert component accepting a type prop ("info" or "error") and children, rendering a colored box (blue for info, red for error) containing whatever children were passed.

📄 View solution
Challenge 3

Build a TwoColumn component accepting left and right props (each containing JSX), rendering them side-by-side in two divs. Use it in App passing different JSX content to each slot.

📄 View solution

Chapter 9 Quick Reference

  • children — automatic prop holding whatever's written between a component's opening/closing tags
  • Composition lets one wrapper component (Card, Panel) work with any content, written once
  • children combines naturally with regular named props (title, type, etc.)
  • JSX can be passed as the value of any prop, not just via children — useful for multi-region layouts
  • Prefer flexible composition over an ever-growing list of configuration props
  • Next chapter: lifting state up — sharing one piece of state between sibling components