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
childrenor via its slots?".