Compound Component is a pattern in React when a component doesn't work by itself and needs other specific components to be its children or parents in order to operate.
Here is an introduction video https://www.youtube.com/watch?v=hEGg-3pIHlE
I know, I'm not supposed to feel emotions about programming patterns, yadda yadda. I don't care. I hate Promises and Compound Components. Can I hate at least two things?
There are 3 main issues:
- Can't be correctly covered with type systems (PropTypes, Flow, TypeScript).
- Nesting doesn't work as usual. Breaks if you extract a child to another component. May break if you nest a child deeper than the first layer.
- It's confusing. When you look at a code that uses this pattern, it's hard to understand how does it really work. Therefore it's harder to make correct changes.
#1
and #2
Ryan describes better than I could in his another video https://www.youtube.com/watch?v=GK_rI4V4tZE .
The video is in fact about new React API that may help to solve these problems.
But until this API is available these two are real problems, and I don't understand how someone
could consider to still use Compound Components as a public API of a library despite these two.
#3
is more controversial, but I think it's also a real problem. And it cannot be fixed using the new API.
Use normal data structures instead of components:
// before
<Foo>
<Bar baz="1" />
<Bar baz="2" />
<Bar baz="3" />
</Foo>
// after
<Foo items={[
{baz: '1'},
{baz: '2'},
{baz: '3'},
]}>
Or, in a more complex case, when you want to allow another markup in between your special parent and child components, make it explicit that the parent communicates with special children. For example like this:
// before
<Foo>
<div>
<Bar baz="1" />
<div><Bar baz="2" /></div>
</div>
</Foo>
// after
<Foo render={context => (
<div>
<Bar baz="1" fooContext={context} />
<div><Bar baz="2" fooContext={context} /></div>
</div>
)} />