Check out a free preview of the full A Tour of JavaScript & React Patterns course
The "Compound Pattern" Lesson is part of the full, A Tour of JavaScript & React Patterns course featured in this preview video. Here's what you'd learn in this lesson:
Lydia introduces the compound pattern and compares it to the provider pattern. With the compound pattern, multiple components work together to perform a single task. The wrapper component can be implemented either with a Provider or using the React.Children.map API.
Transcript from the "Compound Pattern" Lesson
[00:00:00]
>> All right, then moving on to the compound pattern, which is still using the provider pattern by the way. So maybe also if you still have questions, this might clear some things up. But with the compound pattern, we can create multiple components that work together to perform a single task.
[00:00:13]
And this is very nice to use with the provider pattern. So for example here we want to click on a search and again this opens like that, that search bar. Now essentially what happens here is that the search bar and this kind of like fly outs, they all work together, like all those components are performing a single task like the user clicks on the inputs then this input shows these list items.
[00:00:34]
So we could wrap all these components within a provider that provides that data or that state, like okay, is this list item open or is a list open has user clicking it and all that stuff. Now often what you see with the compound pattern and maybe you've used this in like component libraries is that we can import like a single component or like a visual component.
[00:00:56]
And then we can use like dot notation like fly dot input, fly dot list to conditionally render the components that this compound component provided. Hope that was not too confusing. So for example here we have like the fly dot inputs which I tried to make like here, and fly dot list list item.
[00:01:15]
Now you can see here that we don't have any state in the search input itself because that state is contained within the flyout itself. So we can see kind of the implementation here. And we will of course have an exercise that also makes you do this, but so the fly out component here, so that's like the parent that wraps all those smaller components, that's a stateful component.
[00:01:38]
And that provides, all right, yeah so we create a context again like we have for the provider pattern, and this returns a provider that has the open toggle value and set value method, just for this example, of course you can pass anything, and then that renders the children.
[00:01:55]
Now any of those children can use this context or use that consumer components to retrieve the value of to toggle or to set the value to open all the values that we provided here in this provider. Now the cool thing about the compound pattern is that you can also just say like flyout dot input is this input component, flyout dot list is this list component and that makes it super easy, yeah, to create like those sub components because we only have to have like one single import.
[00:02:23]
Like we saw here, we can just do like import flyouts and we don't have to also import like flyout input, flyout list, flyout list item. You don't have to do that with a compound pattern, but it definitely makes it clear like okay, this is just one component and all these sub components, they just like work together.
[00:02:39]
It's just like part of one bigger component. It's not like a standalone component on its own, yeah. Now here we see that we're just rendering it right away. One other way that you might often see it is using the react children map with the clone elements. So instead of directly rendering like props of children like wrapped within that provider, we can also just map all the children and directly pass the props or like these props the open, toggle, value, set value the same like value that provided to the provider before [LAUGH] that we now pass it directly as props.
[00:03:17]
So you can see that here, like props and then like on focus, on blur, children, all those things, so yeah. Let's see, I guess this is just an example. Yeah, so here we're using like it's basically just a real version of the example that we saw before in the animation.
[00:03:39]
So we have like San Francisco, Seattle, Austin, Miami all that stuff, and we can easily render that here. So we're just importing the fly outs, we have the fly out input and we can, if we want to, we could just add more items. I don't know, have multiple boulders for no reason.
[00:03:55]
And then we have, so it's super easy to like add new components and if you are using maybe a component library or something, those components are usually styled. You see this in like material UI, probably many other ones as well. Yeah, we don't have to care about the styling of the components or the state.
[00:04:14]
So it's super easy to render stateful components, but in a very easy, straightforward way. Yeah, so the trade-offs like the pros are kind of what I just talked about having that single import, which is super nice. We don't have to explicitly import all those child components as well.
[00:04:30]
And yeah, so the state management, so any component that uses such a compound component doesn't have to implement its own state, because that's already contained within that compound components. Now the only kind of drawbacks is I guess when you're using react children map, you just have to be more careful with how you're rendering those children.
[00:04:49]
Because it's like only direct children will then get access to like all the props that we pass, but yeah, that's just kind of like implementation details. Same with the naming collisions, maybe the child components that we pass already have props that we're then passing when using react clone elements, cuz it's only performing a shallow merge, but again that's about it.
[00:05:13]
All right, so the last challenge of today, as far as I know, is to create a compound pattern or a compound component. So here we see that we have an input component. I'm just going to make this big real quick, one sec. Okay, so in this input component, we see that we have the state for logic, like set open value, set value toggle.
[00:05:41]
And this one is or this input component is rendering the flyouts. Now you can see that this is not a compound component like we're actually creating all those children ourselves. So instead, what we wanna get is something like we saw before. Like we just wanna be able to import a fly outs and then render a flyout dot input, input list, list item.
[00:06:02]
So it changed this code to create a flyout components that's the input component returns, if that makes sense, clear? And of course, if you need any inspiration, just scroll up a bit and you will probably see the implementation.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops