DEV Community

Cover image for React Design Patterns: Compound Component Pattern
Muhammad Azfar Aslam
Muhammad Azfar Aslam

Posted on

React Design Patterns: Compound Component Pattern

Salut, Hola, Bonjour, Hi and Salam to Everyone

React's flexibility allows developers to create highly reusable and customizable components. One powerful design pattern that leverages this flexibility is the Compound Component Pattern. This pattern enables developers to build components composed of multiple, related sub-components. In this blog post, we'll explore the Compound Component Pattern and demonstrate its use through an example of a card component.

What is the Compound Component Pattern?

The Compound Component Pattern involves creating a parent component that manages state and behavior, and child components that consume and display this state. This pattern allows you to build components that are highly flexible and reusable. The parent component provides context and state, while the child components use this context to render their UI parts.

Advantages of the Compound Component Pattern

  • Flexibility: Child components can be rearranged, omitted, or repeated in different orders.

  • Reusability: Components can be reused in different contexts with varying content.

  • Separation of Concerns: State management and UI rendering are separated, making components easier to maintain and test.

Example: Card Component
Let's build a card component using the Compound Component Pattern. The card will have an image, a title, and a description.
There are two ways to achieve this pattern, I will share both ways.

Approach 1

In this way, we will use normal functions to create compound components as Arrow functions are not hoisted, so you cannot use them before initialization, that's why I am using regular functions.

Create a Card Component
Create a Card.jsx file. In this card component, we will create compound components.

import React from "react";


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

Card.Image = Image;
Card.Title = Title;
Card.Description = Description;

export default Card;

function Image({ src, alt }) {
  return <img className="card-image" src={src} alt={alt} />;
}

function Title({ children }) {
  return <h2 className="card-title">{children}</h2>;
}

function Description({ children }) {
  return <p className="card-description">{children}</p>;
}
Enter fullscreen mode Exit fullscreen mode

Create a styles.css
Let's create a style file to write some basic styling. This is not a CSS tutorial so not going to put much effort into this part. Just some normal CSS.

.app {
  text-align: center;
  display: flex;
  justify-content: center;
  padding-top: 20px;
  gap: 20px;
}
.card {
  border: 1px solid #ddd;
  border-radius: 4px;
  overflow: hidden;
  width: 300px;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}

.card-image {
  width: 100%;
  height: auto;
}

.card-title {
  font-size: 1.5rem;
  margin: 16px;
  color: Blue;
}

.card-description {
  font-size: 1rem;
  margin: 16px;
}

Enter fullscreen mode Exit fullscreen mode

How to use Compound Component
Now let's use these components inside our App.jsx. The styles file is the same as above.

import Card from "./Card";
import "./styles.css";

const App = () => {
  return (
    <div className="app">
      <Card>
        <Card.Image
          src="/reactjs.jpeg"
          alt="Placeholder Image"
        />
        <Card.Title>I'm Azfar Aslam</Card.Title>
        <Card.Description>
          This is a description for the first card. If you like this tutorial,
          please like, subscribe, and share.
        </Card.Description>
      </Card>
      <Card>
        <Card.Image
          src="/reactjs.jpeg"
          alt="Placeholder Image"
        />
        <Card.Title>I'm Lead Web Developer</Card.Title>
        <Card.Description>
          This is a description for the second card. If you like this tutorial,
          please like, subscribe, and share.
        </Card.Description>
      </Card>
    </div>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

Final Result
This is how it will look like at the end. You can see how much control we have in this pattern and reusability.

Image description

Approach 2

In this way, we will create compound components using arrow functions. I am making it all inside one card component file but you can also create separate files.

Create a Card Component
Create a Card.jsx file. In this card component, we will create compound components.

import React from "react";

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

export default Card;

export const CardImage = ({ src, alt }) => {
  return <img className="card-image" src={src} alt={alt} />;
};

export const CardTitle = ({ children }) => {
  return <h2 className="card-title">{children}</h2>;
};

export const CardDescription = ({ children }) => {
  return <p className="card-description">{children}</p>;
};

Enter fullscreen mode Exit fullscreen mode

How to use Compound Component
Now let's use these components inside our App.jsx. The styles file is the same as above.

import Card from "./Card";
import { CardDescription } from "./Card";
import { CardTitle } from "./Card";
import { CardImage } from "./Card";
import "./styles.css";

const App = () => {
  return (
    <div className="app">
      <Card>
        <CardImage
          src="/reactjs.jpeg"
          alt="Placeholder Image"
        />
        <CardTitle>Hello World</CardTitle>
        <CardDescription>
          This is a description for the first card. If you like this tutorial,
          please like, subscribe, and share.
        </CardDescription>
      </Card>
      <Card>
        <CardImage
          src="/reactjs.jpeg"
          alt="Placeholder Image"
        />
        <CardTitle>This is Second Card</CardTitle>
        <CardDescription>
          This is a description for the second card. If you like this tutorial,
          please like, subscribe, and share.
        </CardDescription>
      </Card>
    </div>
  );
};

export default App;

Enter fullscreen mode Exit fullscreen mode

The result will be the same.

Conclusion

The Compound Component Pattern in React allows for building flexible, reusable components by separating state management from UI rendering. By using this pattern, you can create components that are easy to maintain and extend. The card component examples demonstrates how to implement this pattern effectively, providing a robust and scalable solution for complex UIs.

With this pattern, you can create a wide range of components that can be easily customized and reused across your application, enhancing both the developer experience and the application's overall structure.

I hope this will be helpful, love to connect with you on LinkedIn


Few more articles

Top comments (0)