DEV Community

Cover image for Mastering Compound Components: Building Flexible and Reusable React Components
Gabriel Duete
Gabriel Duete

Posted on

Mastering Compound Components: Building Flexible and Reusable React Components

Introduction

One of the most useful and widely used concepts in the world of React is design patterns, as they help keep code scalable and give added meaning to the components we create.

There are various patterns, and in this article, we’ll discuss Compound Components, an advanced pattern that is especially useful for creating flexible and composable interfaces.

What is Compound Components?

Compound Components is an advanced pattern in React. Its goal is to create a more flexible design by enabling the sharing of state and logic among a group of components. This way, communication between the parent component and child components can be achieved in a flexible manner.

The components work together to achieve certain behaviors without creating complex prop trees or overly complicated logic that would be difficult to refactor or understand in the future.

This pattern helps eliminate prop drilling, where we pass down a large number of props through several component layers. Prop drilling can be problematic, as it may cause unnecessary re-renders every time the state is updated, since each state change will update all child components.

An example of Compound Components can be seen in the HTML structure of select and option tags:

image of select and option tags example in html

The select element works as the interface’s state manager, while the option elements configure how the select component should function.

Example Using Compound Components

In this example, we’ll create a Modal, which is divided into two compound components: Toggle and Content. They will share the open/close state of the modal.

Let’s walk through how to create this component step by step:

We can start by creating the context that will manage the open/close state of the modal:

Context to modal component

Creating the base of the Modal component:

Base of the modal component

Notice that we’re using children to grab the components that will be placed inside the Modal. We want to use it like this:

Example of what the component will look like

Now we need to create the toggle component, which will be responsible for opening the Modal:

Component Toggle

We also need a content component that will be responsible for displaying the Modal’s content:

Component content

Finally, we can add both components to our Modal component, and it’s ready to go! 😊

Using the other components in Modal component

Usage:

Using modal component in app

Result:

Visual result of the component’s functionality

This way, we make creating and using modals extremely flexible and reusable. Modal.Toggle is responsible for triggering the modal display, while Modal.Content should display the modal content.

This structure allows developers to easily customize the behavior and content of modals according to the specific needs of their applications, making the code cleaner and more organized.

Other Examples

We can also use Compound Components in other contexts, such as:

Accordion components:

Example of an accordion component using compound components

Menu components:

Example of an menu component using compound components

All of these examples are flexible and adaptable, making development, scalability, and component usage easier.

Exercise

We noticed that the close button was placed inside the content component, but it would be interesting to have a component dedicated to managing the closing of the modal. You could create something like <Modal.Close>Close</Modal.Close>. Try experimenting and adding this component as well!

Conclusion

We’ve seen how writing components using the Compound Components pattern can be useful in our applications. We also explored how to implement it and reviewed examples of where this pattern can fit.

Feel free to explore and experiment with creating components using Compound Components. Use it wisely and assess if it makes sense to apply in your context, as if not implemented well, it could end up being more of a hindrance than a help.

Note: I posted this same content on react4noobs, a BR repository that brings together articles created by developers in the React universe. It’s worth checking out!

Top comments (0)