Composition
Build complex UIs by combining small, focused components.
Composition means building bigger components out of smaller ones. React strongly favors composition over inheritance — you almost never extend components; you nest and combine them.
Patterns
- Pass components as children for generic containers.
- Pass components as props (sometimes called slots) for named regions like a header or sidebar.
Small, single-purpose components are easier to name, test, and reuse.
Example
function Page({ sidebar, children }) {
return (
<div className="layout">
<aside>{sidebar}</aside>
<main>{children}</main>
</div>
);
}
function App() {
return (
<Page sidebar={<nav>Menu</nav>}>
<h1>Dashboard</h1>
</Page>
);
}When to use it
- A page builder assembles Header, Sidebar, ContentArea, and Footer components together inside a PageLayout component instead of putting all markup in one monolithic file.
- A chart dashboard composes ChartTitle, ChartLegend, and ChartCanvas into a ReportCard component so each part can be tested and updated independently.
- A form library exposes a Form component that accepts Field, Label, and ErrorMessage children, letting callers compose the exact form shape they need.
More examples
Compose a page from sections
Composes four independent section components into a page without any shared logic leaking between them.
import Navbar from './Navbar';
import HeroBanner from './HeroBanner';
import FeatureGrid from './FeatureGrid';
import Footer from './Footer';
function HomePage() {
return (
<>
<Navbar />
<HeroBanner />
<FeatureGrid />
<Footer />
</>
);
}Slot-based composition
Accepts named slot props for header, body, and footer so the caller controls each region independently.
function Dialog({ header, body, footer }) {
return (
<div role="dialog" className="dialog">
<div className="dialog__header">{header}</div>
<div className="dialog__body">{body}</div>
<div className="dialog__footer">{footer}</div>
</div>
);
}
// Usage
// <Dialog
// header={<h2>Confirm delete</h2>}
// body={<p>This cannot be undone.</p>}
// footer={<><CancelBtn /><DeleteBtn /></>}
// />Specialised component via composition
Creates a specialised SaveButton by composing the generic IconButton — no class inheritance required.
function IconButton({ icon, label, ...rest }) {
return (
<button className="icon-btn" aria-label={label} {...rest}>
<span className="icon" aria-hidden="true">{icon}</span>
<span className="label">{label}</span>
</button>
);
}
function SaveButton(props) {
return <IconButton icon="💾" label="Save" {...props} />;
}
Discussion