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.