Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Components and JSX  ›  Capstone Project

Composition and children

Composition 15 minComposition builds bigger components by nesting smaller ones, using the children prop and other props to leave slots that the parent fills in.

Composition and children

The reading list now needs a few boxes that all look alike — a border, some padding, a title bar — but hold completely different things. You could write BookBox, SearchBox and StatsBox. Or you could write the box once and let each parent decide what goes inside.

The rule

Build big from small; leave a slot, and let the parent fill it.

Build big from small. Components are combined by nesting them, not by inheriting from each other. React has no need for "a FancyCard that extends Card"; you put a Card inside something else instead.

Leave a slot. Whatever a parent writes between a component's opening and closing tags arrives as a special prop called children:

function Panel({ title, children }) {
  return (
    <section className="panel">
      <h2 className="panel-title">{title}</h2>
      <div className="panel-body">{children}</div>
    </section>
  );
}

Let the parent fill it:

export default function App() {
  return (
    <main>
      <Panel title="My books">
        <BookCard title="Dune" author="Frank Herbert" pages={412} />
      </Panel>
      <Panel title="Stats">
        <p>2 books, 722 pages</p>
      </Panel>
    </main>
  );
}

Panel has no idea what it contains, and that is exactly why it is reusable. You can leave more than one slot, too: any prop can hold JSX, as in <Layout sidebar={<Filters />} main={<BookList />} />.

A pleasant side effect: because App places BookCard directly inside the panel, it passes the book's data straight to BookCard. Panel never has to receive and forward props it does not care about.

The shortcut

When two components differ only in what is inside them, ask: "Is the outside the same?" If yes, make one wrapper and pass the inside as children.

Merging three boxes into oneStep 1 of 4
  1. Compare the outsides

    BookBox, SearchBox and StatsBox all render the same border, padding and title bar.

You have already used this idea without noticing: an HTML <ul> does not care which <li> elements you put in it. Panel behaves the same way, and children can be anything renderable — text, a single element, several elements, or nothing at all.

The trap is forgetting to render {children}. The parent's content is passed in, but if Panel never places it in its JSX, it silently vanishes.

Drills

Answer fast — trust the rule.

quick drill

In <Panel title="Stats"><p>2 books</p></Panel>, how does Panel receive the paragraph?

quick drill

Panel returns <section className="panel"><h2>{title}</h2></section>. What happens to the content passed between its tags?

quick drill

Which is the React way to make a special card that shares a plain card's frame?

quick drill

A layout needs two separate slots, a sidebar and a main area. What works?

Remember

  • Build big from small; leave a slot and let the parent fill it.
  • Same outside, different inside? One wrapper with children.
  • Trap: a wrapper that forgets to render {children} swallows its content.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainA reusable panel

The reading list needs several boxes that look the same (border, padding, a title bar) but hold different things: a book list, a search form, some stats. Explain how to build one Panel component for all of them using composition, and why this beats writing three separate box components.