Search code examples
javascriptreactjstypescriptlayoutreact-functional-component

How to create a react layout component without using props?


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!


Solution

  • 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