Higher order components will allow you to apply behaviors to multiple React components. This can be done by passing the state and any functions into components as props.
[00:00] In this lesson, we're going to talk about higher order components. To get us started, I've got a simple App component here. It's outputting a button component as well as a label component. The button component is a stateless function component, and it outputs props.children as its content. The label component is a full class component, and it also outputs this.props.children as its content.
[00:25] The purpose of a higher order component is to share common functionality or information between multiple components. The sole function of a higher order component is to take in a component and return a new component. We're going to go ahead and call our higher order component HOC. It's going to take in that InnerComponent, and it's going to return class extends React.Component.
[00:54] We can do a lot of things here, but the first thing we're going to do is render our new component. We're simply going to return our InnerComponent, whatever that was, in its JSX syntax. To use this, let's see, on the button, we're going to wrap the entire function in our HOC method. On the label, it's going to create a new component name.
[01:18] We're going to say const LabelHOC = HOC component, and we'll pass it our Label component. Here, where we're using Label, we're going to rename that LabelHOC. The first thing we're going to notice is that our props.children is no longer passing through. When we're creating a higher order component, we need to take that into consideration.
[01:44] The simplest solution to this is to spread this.props into our components so it will pass that information right on through as props. There we can see in the browser our props.children is now coming through. Since our higher order component, in this case, is returning a class component, we can go ahead and add on some component lifecycle methods.
[02:05] Here in the componentWillMount, we'll say "will mount" in the console.log statement. We should see that fire off twice. If our label component, which is also a class component, had its own componentWillMount phase, we could log out there "label will mount." We'll see the higher order component fire off twice. Then we'll see the label component fire off once. There we go.
[02:30] We could also create some state for these guys. Here, in our higher order component, let's set up a constructor. We'll call super in order to get our context. We'll go on and give this some state. We'll say this.state = {count: 0Then we're going to go ahead and set up an update method here. In that, we'll simply increment that state of count. We'll say count: this.state.count + 1.
[02:52] We're going to need to get that state into our components, so we can spread state as a new prop. Then, in our component, let's break this out a little bit, right after props.children we'll say props.count. We'll do the same in our label. Save that. We can see that our count has in fact made it into both of them. Then for the update method, we'll pass that as an additional props.
[03:24] We'll say update={this.update.bind(this)}. Then on our button, we'll say onClick={props.update}. Save that. As we click on the button, it is updating that state. On the label, we'll say onMouseMove={this.props.update}. Clean that up a little bit. Save that. On our button, the state of count is updated when we click on it. On the label, it's updated when we move the mouse.
The spread operator is an ES6 feature, not a React feature. It's a direct way to access a collection as an iterable. So if you had an array like let myArray = [0, 1, 2, 3]
you can access every element with the spread operator. console.log(...myArray)
would output 0 1 2 3
. Math.max(...myArray)
would output 3
. Please let me know if my explanation was any good.
I also do not understand the use of the spread operator in there. how does this translate into an components attribute if these are basically just values?
Does
return <InnerComponent
{...this.state}
/>
becomes to something like
<InnerComponent val="3"/>
?
Exactly. You could achieve the same thing like this:
return <InnerComponent val={this.state.val} txt={this.props.txt} />
what if the component has a state called "val": this.state = {val: '0'}, and also has a prop called "val": this.props.val = '1'. Is React smart enough to carry over same name state and props when using spread operator?
No, React is not going to differentiate between two values for 'val' passed into a components props. This is not a React-specific issue, it's just something you shouldn't do in JS in general. The outcome will be that the last one passed in will win.
What’s the advantage of composing React components with a higher order component as opposed to class inheritance? If there is functionality that we wanted both the Label and Button to have, couldn’t we also have them both inherit from some other component?
What text editor is he using?
it'd be cool if you can explain a bit more on the spread operator, had a look at react's doc, was not very clear