DevPath · Learn to code ESPTEN

Composition: children and slots

Composition vs inheritance

React prefers composition

In classic object-oriented programming, to reuse behavior you use inheritance: a class RedButton extends Button. React does not follow that path. The way to reuse and specialize in React is composition: you build components by combining other components and passing them content via children or via slots.

// Instead of "inheriting" from Dialog, you COMPOSE it:
function WelcomeDialog() {
  return (
    <Dialog title="Welcome">
      <p>Thanks for signing up.</p>
    </Dialog>
  );
}

WelcomeDialog is a specialized case of Dialog, but achieved by filling its holes, not by extending a class. React's official documentation sums it up like this: we haven't found any use cases where we would recommend creating component inheritance hierarchies.

Compound components (at a high level)

When several pieces work together and share state, a richer composition pattern emerges: compound components. They are a parent component and several children meant to be used together:

<Tabs>
  <Tab title="Profile">...</Tab>
  <Tab title="Settings">...</Tab>
</Tabs>

Tabs coordinates which tab is active; each Tab is a piece that only makes sense inside Tabs. The user composes the interface by declaring the pieces, and the parent handles the shared logic (usually with createContext, which you'll see later).

Key idea: in React you compose interfaces as if they were Lego pieces. Before thinking about "inheriting", think "which component wraps which?" and "what do I pass it via children or via its slots?".

Put this into practice

DevPath is a hands-on course: you read the theory here; in the app you put it into practice with exercises that really run, offline.

Start free in the app →
← Slots: passing elements via propsView the module →