Archive

Originally published 2 min readReact

Compound Components: What, Why and When.

From the archive · written in 2020

What are Compound Components? #

It’s a base component that expects to be combined with other component parts. Below the <Multiselect /> is the base component and the <Option /> and <Group /> components are the composable parts.

<Multiselect
  selectedValues={[1, 2]}
  onSelectedValuesChange={newValues => /* ... */}/>
  <Option optionValue={1}>One</Option>
  <Group header="The best numbers">
    <Option optionValue={2}>Two</Option>
    <Option optionValue={3}>Three</Option>
  </Group>
</Multiselect>

It differs from the use of { children } props where you are not expecting any components in particular.

<Box>
  <Header title="My Work" />
  <Content>Lots of good stuff</Context>
</Box>

While the <Multiselect /> children will accept any components, having a combination of a base and a part component like <Option /> that is intended to be used with it passes our Compound Component definition.

Why would you opt for this pattern? #

The main advantage that the Compound Component pattern version offers is its flexibility. Want to make a <Multiselect /> of people that includes their avatar? Easy.

<Multiselect
  selectedValues={[1, 2]}
  onSelectedValuesChange={newValues => /* ... */}/>
  <PersonOption personId={1}>Jane</Option>
  <PersonOption personId={2}>John</Option>
</Multiselect>

We can support many variations without having to change the base components code.

To mirror the same behaviour using strict props we need to start adding flags like isPersonOptions:

<Multiselect
  selectedValues={[1, 2]}
  onSelectedValuesChange={newValues => /* ... */}
  isPersonOptions={true}
  options={[
    {name: 'Jane', id: 1},
    {name: 'John', id: 2},
  ]}/>
</Multiselect>

More flags will build up over time and the complexity will grow.

When should you use it? #

It’s when you need flexibility. Are you building something that will be widely used?

See React Component API Design for API design alternatives.

Thanks for reading.

More from the archive