advanced react patterns compound components

Compound Components

Compound components is a pattern in which components are used together that they share an implicit state that let them communicate with each other in the background.

Think of compound components like the <select> and <option> elements in HTML.
Apart they don’t do too much, but together they allow you to create the complete experience. — Kent C. Dodds
select tag

If you were to try and use one without the other it wouldn't work (or make sense). Additionally it's actually a really great API, let's check out what it would look like if we didn't have a compound components API to work with (remember, this is HTML, not JSX):

ugly select tag

it's a mess, so the compound components API gives you a nice way to express relationships between components.

Another important aspect of this is the concept of "implicit state." The <select> element implicitly stores state about the selected option and shares that with its children so they know how to render themselves based on that state. But that state sharing is implicit because there's nothing in our HTML code that can even access the state (and it doesn't need to anyway).

Alright, let's get a look at a legit React component that exposes a compound component to understand these principles further.

Here's an example of the <Form /> component from Semantic Ui React that exposes a compound components API:

semantic ui form compound component

In this example, the <Form> establishes some shared implicit state. The <Form.Group>, <Form.Input>, <Form.Select> and <Form.Button>  components each access and/or manipulate that state, and it's all done implicitly. This allows you to have the expressive API you're looking for.

So we will try to build a simple navigation bar where all its nav elements will share the same implicit state using context api and we will apply a different background color for the active nav element.

So here is how our Nav Component look like :

Nav compound component

And here is how we call it in our App(root) Component :

root App

You can find the whole code in CodeSandbox

nav compound component app

Thanks for reading!


PS : to get more details about this awesome pattern watch this React Hooks: Refactor compound components to hooks.