`this`: the keyword
This is going to be a very brief overview of the keyword this
, if you finish and would like to read about it more in depth you can do so here.
First let's look at the keyword this
in a constructor function in Vanilla JS.
function Person (name, age, hairColor){
this.name = name;
this.age = age;
this.hairColor = hairColor;
console.log(this)
}
const john = new Person('john', 25, 'brown');
//this will console log `Person { name: 'john', age: 25, hairColor: 'brown' }`
As you can see in the example above, the keyword this
is simply the instantiated version of the Person
constructor.
It is basically replacing the word Person
as the name of the object. If I wanted to console log the age then rather than writing console.log(Person.age)
you would write console.log(this.age)
.
This can be demonstrated when we create a method in our Person
constructor
function Person (name, age, hairColor){
this.name = name;
this.age = age;
this.hairColor = hairColor;
this.speak = function (){
console.log(`Hello, my name is ${this.name}`)
}
}
Notice once again that we use this.name
instead of Person.name
. That is because this
is scoped to the Person
constructor.
If we tried console.log(this)
outside of that function, it would grab the window object.
This: in React
We are going to take a look at this
in the context of this Toggle component in react.
import React, {Component} from 'react';
class Toggle extends Component {
constructor(props) {
super(props);
this.state = {
toggleOn: false
};
console.log(this)
}
handleClick() {
this.setState(prevState => ({
toggleOn: !prevState.toggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
export default Toggle
Notice that I am console logging this
up in the constructor. That will print the following to the console.
Everything that was console logged is something that you can access after the keyword this
. For example, this.state
, or this.props
. These are all part of the Toggle component which inherited all of these from React.Component.
If we instead had a function based Toggle component like this:
import React from 'react';
const Toggle = () => {
console.log(this)
return (
<div>
</div>
);
};
export default Toggle;
Then the console log would look more like the following:
But let's go back to our Class Based Toggle Component for now. If we tried to run our handleClick
function as it currently stands, it would deliver the following error.
.setState()
is a method that is part of our constructor. So when we say this
inside of the handleClick
function, it returns undefined
because the this
in our handleClick
is scoped to that specific function rather than to our constructor.
There are two ways we can fix this:
class Toggle extends Component {
constructor(props) {
super(props);
this.state = {
toggleOn: false
};
//you can add this line
**this.handleClick = this.handleClick.bind(this);**
console.log(this)
}
or
//you can turn your function into a fat arrow function
handleClick = () => {
this.setState(prevState => ({
toggleOn: !prevState.toggleOn
}));
}
After we do one of these if we look at the console.log of this
, you will notice that it now includes our function handleChange
.