I've seen the following pattern a lot in primitive components (like Radix UI) where layouts are rendered as custom children components. For example instead of this:
<List
title="Hello!"
items={
['Item 1', 'Item 2', 'Item 3']
}
/>
the primitives will use this:
<List.Root>
<List.Title>Hello!</List.Title>
<List.Items>
<List.Item>Item 1</List.Item>
<List.Item>Item 2</List.Item>
<List.Item>Item 3</List.Item>
<List.Items>
<List.Root>
This will end up rendering some custom layout with styles, etc, like the following:
<div>
<span>Hello!</span>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</div>
My question is: what even is the name of this pattern, and how would I achieve it using functional components? How would I pass states between each of the elements? I've looked at the source for some of the Radix components, but they all use some sort of abstracted primitives, and a lot of Contexts
.
The example above is pretty simple, but you can imagine this being used for more complex layouts. For example, a layout that returns two columns, where instead of passing column1
and column2
, you just pass <Layout.First>...</Layout.First>
and <Layout.Second>...</Layout.Second>
.
Any help would be appreciated!
It looks like this pattern is called a Compound Component. The key is utilizing react's Context
API.
Here's a pretty good tutorial that goes into more depth on how to actually create a compound component: https://blog.cristiana.tech/building-compound-components-using-react-context-api-and-typescript