React Design Patterns: Compound Component Pattern
Tags: javascript, react, designpatterns, nextjs
Published: 2024-07-10 10:27:30

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>;
}
```

**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;
}

```

**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;
```

**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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gpuvo5tlmno8u29tjfus.png)




## 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>;
};

```

**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;

```

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](https://www.linkedin.com/in/muhammad-azfar-aslam)

__________________________________________________________________

**Few more articles**
- [Managing Global State with useReducer and Context API in Next JS 14](https://dev.to/muhammadazfaraslam/managing-global-state-with-usereducer-and-context-api-in-next-js-14-2m17)
- [Highlight on the new features of Next JS 14 config 2023](https://dev.to/muhammadazfaraslam/highlight-on-the-new-features-of-next-js-14-config-2023-4lbe)
- [How to configure React JS app on WSL2 Windows 10](https://dev.to/muhammadazfaraslam/how-to-configure-react-js-app-on-wsl2-windows-10-3d1n)
- [Custom 'Tooltip' component using Tailwind and React Js](https://dev.to/muhammadazfaraslam/custom-tooltip-component-using-tailwind-and-react-js-186g)
- [JavaScript and React Interview questions (Junior/Mid-level) 2023](https://dev.to/muhammadazfaraslam/javascript-and-react-interview-questions-juniormid-level-2023-hd1)