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.