DevAcademy
LearnReactComponent Composition
BeginnerReact

Component Composition

Learn how to compose components together using children and slot-like patterns, instead of deep prop chains.

Reading Time

14 min

Lesson

Lesson 10 of 42

Composition Over Configuration

Instead of building one component with dozens of props to handle every possible variation, React favors composing smaller components together — nesting them the way you’d nest HTML elements.

A Reusable Layout Component

function Card({ children }) {
  return <div className="card">{children}</div>;
}

function App() {
  return (
    <Card>
      <h2>Card Title</h2>
      <p>Any content can go here.</p>
    </Card>
  );
}

Multiple "Slots" with Named Props

When a component needs more than one distinct content area, pass JSX through regular props (not just children) to create multiple "slots."

Multiple Content Slots

function SplitPanel({ left, right }) {
  return (
    <div style={{ display: "flex" }}>
      <div className="left">{left}</div>
      <div className="right">{right}</div>
    </div>
  );
}

function App() {
  return (
    <SplitPanel
      left={<Sidebar />}
      right={<MainContent />}
    />
  );
}

Avoiding "Prop Drilling"

Composition also helps avoid prop drilling — passing a prop through several intermediate components that don’t use it themselves, just to reach a deeply nested child. Passing already-rendered JSX as children skips the layers that don’t need the data at all.

Composition Avoids an Unnecessary Prop Chain

// Instead of threading 'user' through Layout and Sidebar just to reach Profile:
function Layout({ children }) {
  return <div className="layout">{children}</div>;
}

function App({ user }) {
  return (
    <Layout>
      <Profile user={user} />
    </Layout>
  );
}
// Layout never needs to know about 'user' at all

Building Specialized Components from Generic Ones

A generic, flexible component can be wrapped to create a more specialized version with sensible defaults, without duplicating its implementation.

A Specialized Button Built from a Generic One

function Button({ variant = "default", ...props }) {
  return <button className={`btn btn-${variant}`} {...props} />;
}

function DangerButton(props) {
  return <Button variant="danger" {...props} />;
}

Best Practice

When you notice a prop being passed through several components that never use it themselves, look for a way to restructure with composition (children or named JSX slots) before reaching for Context — composition often solves the problem more simply.

Interview Questions

Quick Quiz

1. What is "prop drilling"?

2. How can a component accept more than one distinct content area, beyond just children?

3. What is one benefit of favoring composition over one large, heavily-configured component?