MSDN Documentation

Component Composition

Component composition is a fundamental pattern in modern UI development, allowing you to build complex user interfaces by combining smaller, reusable components. This approach promotes modularity, maintainability, and testability.

What is Component Composition?

Instead of creating monolithic components that handle too many responsibilities, you break down your UI into distinct, single-purpose components. These components can then be assembled like building blocks to create more intricate UIs. This is often achieved through props, slots, or render functions, depending on the framework or library you're using.

Key Principles

Composition with Props

A common way to compose components is by passing data and functions as props. A parent component can render child components and configure them by providing specific props.

Example: Passing Content via Props

Imagine a Card component that can display different content:

// Card Component (Simplified)
function Card({ title, children }) {
  return (
    <div class="card">
      <h3>{title}</h3>
      <div class="card-content">
        {children}
      </div>
    </div>
  );
}

// Usage in a Parent Component
function App() {
  return (
    <div>
      <Card title="Welcome!">
        <p>This is the content of the first card.</p>
      </Card>
      <Card title="Another Section">
        <ul>
          <li>Item 1</li>
          <li>Item 2</li>
        </ul>
      </Card>
    </div>
  );
}

Here, the Card component accepts a title prop and uses a children prop to render arbitrary content passed from its parent. This makes Card highly reusable.

Composition with Slots (or Render Props)

Some frameworks provide mechanisms like "slots" or use patterns like "render props" to allow components to inject content or behavior into specific areas of another component's template. This is particularly useful for layout components or components that provide a common structure but need customizable internal parts.

Example: Using Slots/Render Props

Consider a Modal component that has predefined header and footer areas but allows the content to be defined by the parent:

// Modal Component (Conceptual)
function Modal({ headerContent, footerContent, children }) {
  return (
    <div class="modal-overlay">
      <div class="modal">
        <div class="modal-header">{headerContent}</div>
        <div class="modal-body">{children}</div>
        <div class="modal-footer">{footerContent}</div>
      </div>
    </div>
  );
}

// Usage
function MyPage() {
  return (
    <Modal
      headerContent={<h2>My Custom Modal</h2>}
      footerContent={<button>Close</button>}
    >
      <p>This is the dynamic content inside the modal.</p>
      <input type="text" placeholder="Enter something..." />
    </Modal>
  );
}

In this pattern, headerContent, footerContent, and children act as customizable insertion points, allowing for flexible composition.

Benefits of Component Composition

Embracing component composition is key to building robust, scalable, and maintainable user interfaces. By breaking down UIs into smaller, manageable pieces and composing them together, you create a more elegant and efficient development process.