DEV Community

Cover image for Composition vs Compound Components in React
Duffman
Duffman

Posted on

Composition vs Compound Components in React

In React, reusable UI usually follows two patterns: composition components and compound components. They are closely related, but they differ mainly in how state is handled and how the API is exposed.

Composition Components (no Context)

This is the most straightforward approach. You build UI by combining components and passing data through props.

Everything is explicit: each component receives what it needs directly from its parent.

This makes the system very flexible and easy to reuse, since every part is independent. You can take a subcomponent and use it anywhere without constraints.

The downside is that as the UI grows, you often end up with prop drilling and a lot of wiring code. Sharing behavior between related parts also becomes harder because there is no shared state mechanism.

In short: simple, explicit, and flexible, but can become verbose in complex UIs.

import Airbnb from "./Airbnb";

<Airbnb.Card>
  <Airbnb.ImageWrapper>
    <Airbnb.Image src={el.image} alt={el.title} />
    <Airbnb.Heart like={el.isFavorite} onClick={() => {}} />
    <Airbnb.Recomendation />
  </Airbnb.ImageWrapper>
  <Airbnb.Content>
    <Airbnb.Title title={el.title}>
      <Airbnb.Valoration average={el.average} reviews={el.reviews} />
    </Airbnb.Title>
    <Airbnb.Description description={el.description} />
    <Airbnb.Price price={el.price} nights={el.nights} />
    <Airbnb.Cancelation />
  </Airbnb.Content>
</Airbnb.Card>;
Enter fullscreen mode Exit fullscreen mode

๐Ÿ‘‰ Try it in practice: Composition Components Challenge

Compound Components (with Context)

This pattern introduces shared state using React Context. Instead of passing props through every level, a parent component provides state and child components consume it directly.

This creates a tighter relationship between components. From the outside, the API becomes very clean because users donโ€™t need to manage all the props manually.

It works especially well for structured UI systems where components are meant to work together (like cards, modals, tabs, etc.).

The trade-off is that the relationship becomes implicit. Subcomponents depend on a parent provider and are not really meant to be used in isolation. Debugging can also be slightly less obvious because the data flow is hidden inside Context.

In short: more structured, cleaner API, but less flexible and more coupled.

import Airbnb from "./Airbnb";

<Airbnb.Card data={el}>
  <Airbnb.ImageWrapper>
    <Airbnb.Image />
    <Airbnb.Heart />
    <Airbnb.Recomendation />
  </Airbnb.ImageWrapper>
  <Airbnb.Content>
    <Airbnb.Title>
      <Airbnb.Valoration />
    </Airbnb.Title>
    <Airbnb.Description />
    <Airbnb.Price />
    <Airbnb.Cancelation />
  </Airbnb.Content>
</Airbnb.Card>;
Enter fullscreen mode Exit fullscreen mode

๐Ÿ‘‰ Try it in practice: Compound Components Challenge

Export styles

There are two common ways to expose these components.

Named exports give maximum flexibility and are easy to tree-shake, but they donโ€™t communicate relationships between components very well.

import { Card, ImageWrapper, Image } from "./Airbnb";

<Card data={el}>
  <ImageWrapper>
    <Image />
  </ImageWrapper>
</Card>;
Enter fullscreen mode Exit fullscreen mode

Namespaced exports group everything under a single object, which makes the structure much clearer and is often preferred for compound components or design systems. The trade-off is slightly more verbosity and sometimes less optimal tree-shaking.

import Airbnb from "./Airbnb";

<Airbnb.Card data={el}>
  <Airbnb.ImageWrapper>
    <Airbnb.Image />
  </Airbnb.ImageWrapper>
</Airbnb.Card>;
Enter fullscreen mode Exit fullscreen mode

When to use each

Use composition when components are independent and you want full flexibility with explicit data flow.

Use compound components when the UI pieces are strongly related, share state, and benefit from a controlled and clean API.

Summary

Composition is about flexibility and explicitness.

Compound components are about structure and shared state.

Both are just different ways of organizing the same idea: composition in React.

Top comments (0)