4.2 Higher-Order Components
Organizing our UI into components makes it easy to reuse code. However, there are times when we need to extend an existing component for more specialized functionality. We could use inheritance, but the React way is to define a "higher-order component". In this lesson I'll show you how easy it is to work with higher-order components.
1.Introduction1 lesson, 01:37
2.Hello, World2 lessons, 16:56
3.Bootstrap Button Group Component2 lessons, 20:48
4.A Digital Clock2 lessons, 20:41
5.A Multi-Selector Component1 lesson, 15:00
6.An Ajax-Powered Navbar2 lessons, 23:54
7.Conclusion1 lesson, 01:35
4.2 Higher-Order Components
There are two ways that we can extend the functionality of a component. The first relies upon inheritance. And that's really only useful if you write your component as a class. Because then you can use the extends keyword, and extend that. So in our case of Clock, we could come in here and we could say class ExtendedClock extends Clock,and so on and so forth. And that would work. However, that's not the best way to do this, at least as far as the people at Facebook are concerned. In fact, if you look at the documentation, they say that they've written tons of components, but they have never used inheritance once in order to do it. Because they think it's better to use what's called a higher ordered component. Now, I have to admit that the first time I saw a higher ordered component, I had to stare at the code a little bit just to fully understand what was going on. And I realized that a higher ordered component is nothing more than a component that wraps around another component. So let's define some terms so that we can make some sense out of this. The first is called the Wrapper Component. Now this is typically the component that has the functionality that we want to reuse. So in our case that is our Clock component. Because this has all of the functionality that we want to reuse, we just want to change how we display the date information. We want to make it flexible so that we can create different components to display the date and time differently. So our Wrapper Component in our case is going to be the clock. The other component is the Wrapped Component. And this has the functionality that we want to extend the Wrapper Component with. And it's typically a more simple component, but that's not always the case. In our case it is. But we have those two components. We have the Wrapper Component that has the core functionality that we want to reuse. Then we have the Wrapped Component that contains the functionality that we want to extend the Wrapper Component with. So let's start with a function that is going to do this wrapping for us. And we're going to call this clockWithDisplay. We are going to accept a parameter, which is going to be our DisplayComponent, that is going to be our Wrapped Component. And then this is where things become a little confusing. Because I have to admit that the first time I saw this, I did not know that you could do this. Return class extends React.Component. So this is going to be the code for our Clock component. We are now going to lose the Clock component as it is right now. So we won't be able to do this down here whenever we call ReactDOM.render. But that's okay, because instead we want to create new components that are based upon this Clock component that wrap around other components for display. So we're basically just going to take the contents of that class and then just put it here inside of this other class. So this is what we have, we have a function that is going to accept a component. And then it's going to return a component, the constructor, the componentDidMount. The tick method, getOffsetDate, the render method. We saw all of this in the previous lesson. The only difference now is here inside of the render method, we are no longer controlling how we display that. Instead we're going to use this DisplayComponent. We'll pass in the date and we will get that value from our state and there we go. So now we can write a component. And this is why higher ordered components are the better option. Because you can extend any type of component. It doesn't have to be a class, it doesn't have to be a function. And you can mix and match, so we can write a simple function. We can call it DisplayTimeClock. Let's have our props, and then we will simply return. We'll have our p element. We will use our props.date, and then the ToLocaleTimeString. So essentially what we had in the previous lesson, but now it is outside of our Clock component and it is controlled here. So we have a class and we are extending that class with a function. And that's what makes higher ordered components a better option. Because you don't have to extend a class with another class. You don't have to try to extend a function with another function. You can mix and match however you want. So let's write another one that is going to be used to DisplayDate and TimeClock. We need our props, and this is going to essentially be the same thing except that we are going say props.date and then toLocaleString. And that will be our second clock. So now we just need to wrap these two components to create our higher ordered components. So let's make these constant because we don't want these to change. And we'll say TimeClock =, and we will call the clockWithDisplay. We'll pass in DisplayTimeClock, and that's it. For our other, we'll say DateTimeClock = clockWithDisplay, and that is the DisplayDateTimeClock. So now we use these components whenever we render them. So let's change our usages of these Clock components. We're gonna use TimeClock in that case. We are going to use the DateTimeClock, that's not click, we're going to use that for our second. We can still use the hourOffset because the hourOffset is part of the core functionality of what used to be our Clock component. So now we can go to the browser, let's refresh the page, and we can see the difference. We have the original version of just the time, but now we also have the date and time as well. Now one thing that I want to point out is that we have a stateful component here that was our Clock component. And then we have stateless components. Now these components don't care about the state of our Clock component. It doesn't need that state. All it needs is the data, the date, in order to display that information. So to briefly recap, we have two components. We have a Wrapper Component and a Wrapped Component. The Wrapper Component has the core functionality that we want to reuse. And that wraps around the Wrapped Component that contains the functionality that we want to extend the Wrapper Component with.