‫Now, let's learn about the most awesome
‫and by far my favorite React pattern,
‫which is the Compound Component pattern.
‫And as a starting point to this example
‫that we're going to build together,
‫we have yet another code sandbox.
‫And I will share the link to this one as always
‫in this lecture's resources.
‫Now let's start by forking this one,
‫so that you can get your own copy,
‫and then let's start by understanding
‫what the Compound Component pattern is all about.
‫So, the idea of a Compound Component
‫is that we can create a set of related components
‫that together achieve a common and useful task,
‫for example, implementing a counter,
‫such as we are going to do in this lecture.
‫But of course, this pattern can also be used in all kinds
‫of components that are actually more useful,
‫for example modal windows, pagination, tables,
‫and so on.
‫So basically, the way we implement
‫this is that we create a parent component,
‫and then a few different child components
‫that really belong to the parent,
‫and that really only make sense when used together
‫with the parent component.
‫And a good example of this is the HTML select
‫and option elements.
‫So the select element implements a select box
‫and the option element implements each
‫of the select options inside the select box.
‫Right?
‫So we have used this kind of HTML all the time.
‫And so these option elements can really only be used
‫inside a select element.
‫So they only make sense within that element.
‫And so this is essentially exactly the same principle
‫as we are going to use in compound components.
‫And this will then allow us to implement highly flexible
‫and highly reusable components
‫with a very, very expressive API.
‫And all without basically using no props at all.
‫So after implementing this example,
‫and the next ones in the next few videos,
‫you will see the potential for using this everywhere.
‫And let me actually start by showing you
‫how we are going to use the component that we're going
‫to build in practice.
‫So that will then show you how this really
‫is super flexible and reusable.
‫So, let's say that we have a counter and nevermind
‫about this other one that we have here.
‫We will talk about that one in a second.
‫And then let's say we close it here immediately.
‫And then in there,
‫let's say we have a counter dot label component.
‫Then we close that.
‫And here, for example,
‫we can say my super flexible counter.
‫Then let's also say we have an increase button.
‫So let's self-close this one.
‫And then here we might want to pass in an icon,
‫for example, like the plus icon.
‫And maybe we also have a decrease component.
‫And all of this, of course,
‫will make more sense when we actually implement this.
‫And then in the end,
‫let's say we also then have a counter.count,
‫where we actually display the result of the counter.
‫And so all of this is now super flexible, because we could,
‫for example, just move this count here,
‫and maybe do the increase here and a decrease here.
‫And maybe we want a label here at the very end,
‫or maybe we don't want a label at all.
‫And so, we can very easily configure all of this simply
‫by moving around the components.
‫And the alternative to doing this would be to create tons
‫of props to exactly configure the component
‫as we wanted.
‫And so that would then create a so-called
‫prop explosion like we have it here.
‫So here we pass in all these different props
‫for all these things.
‫And then here we, for example,
‫have this one to hide the label,
‫while here we could simply delete this,
‫or just simply not write it at all.
‫Or we have height increase or height decrease,
‫where again here we would just have to delete this.
‫And, of course, this wouldn't even be enough.
‫So we might have to also define something like
‫position count or something like this.
‫And then here, maybe we have to write top.
‫So, I'm just making things up here
‫because this is just to show that without the flexibility
‫of a compound component like this one,
‫we would have to pass in 10 or 20 props to configure it
‫in the same way that we can easily achieve like this.
‫And that's not even the only advantage,
‫as you will see later.
‫So once we actually start implementing this.
‫And actually, let's start doing that right now.
‫So there's no need to wait,
‫because we already know what we want to do.
‫So, how can we build something like this?
‫Well, first of all, here we have the counter component.
‫And so this one here should probably keep the state
‫of what the count actually is.
‫So let's open up our files,
‫because I already have this counter.js.
‫And so here, let's add
‫that count value.
‫So, count and set count is equal
‫to useState.
‫And let's start at zero
‫and then import useState,
‫of course from React.
‫And let's also immediately create some simple
‫handler functions here.
‫And let's make them arrow functions called increase.
‫So, just setcount.
‫And then let's do another one
‫for decrease like this.
‫Great.
‫So this is already a starting point,
‫but really just a small starting point.
‫Because how can we now implement something like this?
‫So for example, how can discount value
‫like here actually know what the current state is
‫in this counter component?
‫Because I mean, we are not passing any props
‫between here.
‫And so again, how will this component here know
‫what the current state is?
‫Or also, how will this component right here know how
‫to increase the state and this one how to decrease it?
‫Well, as we just mentioned, we cannot use props for that.
‫But thankfully for us, we have another solution,
‫which is to actually use context.
‫And yeah, you heard that right.
‫We are going to use context to implement
‫the compound component pattern.
‫And so this is a really great use case for the context API.
‫Maybe if you ask me, even the greatest use case.
‫And so, let's create ourselves a new context.
‫So, let's call it the Counter Context,
‫and then create context.
‫And we don't need any default value here.
‫So before we go any further,
‫let's establish how we actually
‫implement a compound component.
‫So, the first step is to indeed create a context.
‫Then next up, we create the parent component.
‫So create the parent component,
‫then afterwards, we need to create
‫the child components that will help implementing
‫the common task
‫of this overall compound component.
‫So basically, those are going to be the decrease, count,
‫increase, and label components.
‫And so then afterwards in the end
‫we add the child components as properties
‫to the parent component.
‫And this step is actually optional,
‫but I really like to do it like this.
‫So then we only have to export the counter,
‫and the rest will just work.
‫All right, so this is basically always the recipe
‫that you are going to follow when you use this pattern.
‫And so, now let's use the context here to provide the state
‫to all our child components.
‫So, here we do
‫counter context.provider, remember.
‫So, we haven't used this for some time.
‫So, this is also a great refresher.
‫So, we want to pass the count,
‫the increase and the decrease functions here
‫to child components.
‫Let's close this.
‫And then here we will need the children, right?
‫And actually, let's wrap them in some other element here,
‫maybe a span.
‫So to make this a bit more flexible even,
‫because if we used a div,
‫that would then create a line break.
‫But then here we need the children prop to then place
‫whatever we pass into the counter.
‫So, basically these three or these four components here
‫will then become the children.
‫So, they will be placed here
‫and therefore they then get access to these three values
‫that we placed in the context.
‫And so let's now actually go ahead
‫and create those components.
‫So that's the counter.
‫Then also the label,
‫then increase
‫and decrease.
‫And so, now let's implement them one by one.
‫And here this one actually needs to be called just count
‫because this will only display the value itself.
‫And so, now we can use the use context hook,
‫and we then need to pass in the context itself.
‫So the counter context.
‫And then from there, we just take the count value.
‫And then we simply return that inside a span element.
‫Then here inside the label,
‫we just want to accept the children
‫and then basically immediately return them.
‫And also inside a span
‫so they don't create any line breaks.
‫Okay.
‫And then finally, the increase and decrease.
‫So, here we need to grab this function
‫again from the context.
‫So use context and then counter context.
‫And then we want to return a button
‫with the onClick prop set to increase.
‫And then here, let's actually accept a prop called icon,
‫so that the user of this component can use that here.
‫And now I will just
‫copy and paste this.
‫So decrease,
‫and there we go.
‫And so now the final step is actually pretty easy.
‫So, we just need to place them here
‫on the counter component.
‫And this is possible because this is simply a function.
‫So in JavaScript, we can add properties almost
‫to everything.
‫And so that includes functions.
‫So, we can do counter.count
‫should be equal
‫to the count component like this.
‫And then we just do the same for all the other ones.
‫So, counter.label will be the label,
‫counter.increase will be increase,
‫and counter.decrease will be decrease.
‫And that's actually it.
‫This is how we implement a counter
‫as a compound component.
‫Now, this might look pretty silly
‫for just implementing a counter.
‫And the truth is that this does require us
‫to write a lot more code and it might be a bit harder
‫to implement as well.
‫But as we saw earlier,
‫there are also many advantages to this.
‫So, let's now deactivate this one right here.
‫Let's then make a hard reload and it looks like it works.
‫And indeed, it does.
‫Great.
‫And so now we can do everything
‫that I mentioned earlier.
‫So we can place this here.
‫So then that changes.
‫We can change here the position
‫of all of the elements inside our counter.
‫And of course, we can omit some of them altogether.
‫So, let's create ourselves another instance here.
‫And so this will then appear here right by the side
‫because we decided to make the counter basically a span
‫with this here, right?
‫So, maybe let's wrap this one here in a div element.
‫Yeah, that's a bit better.
‫And yeah, as I was saying, we can, for example,
‫just completely omit this one, can place this in the center.
‫Here let's maybe use an emoji.
‫So to decrease, we can use this one
‫and to increase this other one right here.
‫And so look how flexible this is.
‫We could even place this one here, of course,
‫in a div as well.
‫So there's nothing stopping us
‫from also using some HTML in here.
‫And so, this is just so flexible.
‫And also the state is so nicely encapsulated now
‫inside this component.
‫And it's completely invisible to the outside.
‫And we could keep going here,
‫but I think you got the point, which is, again,
‫that we have all these different child components here
‫that together help implement a common goal.
‫So in this case, to implement a counter.
‫And each of them on their own
‫don't really make any sense at all.
‫So, if we were trying to use that outside here on its own,
‫then that wouldn't really work at all.
‫The only thing that might work would be this label,
‫I guess.
‫And even then I'm not sure.
‫So just making this up.
‫But yeah, so this one would work.
‫But of, of course, this still doesn't make any sense at all.
‫So this component here really only helps us implementing
‫this bigger counter.
‫And so yeah, this is how in a nutshell
‫the compound component pattern works.
‫And so congratulations, you now,
‫know about the most amazing React pattern that exists.
‫And so luckily for you,
‫you are now one of the few React developers
‫that even knows that this pattern exists and how to use it.
‫But of course, we need to practice this now a bit more
‫and use it in a more real-world situation.
‫And so over the next few lectures,
‫we are going to implement a super-flexible
‫and super-standalone modal window component.