1

For event handlers inside the class component binding is required ( information from lots of sources) . But when console logging the 'this' keyword it logs 'context:undefined' ( because class body is strict as far I know) . And if I console log 'this' inside the event handler ( in this case the changeColor) it logs 'context:{...}' .

    class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = { color:green}; 
    console.log(this); **// Toggle { ... context:undefined..... }**
    this.changeColor = this.changeColor.bind(this);
     }

     changeColor() {
       
       console.log(this);  **// Toggle { ... context:{..} ..... }**
       const newColor = this.state.color==green?yellow:green;
       this.setState({color:newColor});
     }
  render() {
    return (
      <div style={{background:this.state.color}}>
        <h1>
          Change my color
        </h1>
        <button onClick={this.changeColor}>
          Change color
        </button>
      </div>
    );
  }
}

If 'this' is undefined , what are we binding ?

  • [How to access the correct `this` inside a callback?](https://stackoverflow.com/q/20279484) | [How does the “this” keyword work?](https://stackoverflow.com/q/3127429) – VLAZ Nov 19 '20 at 10:57
  • @VLAZ Not exactly, but this is totally different in React. – Praveen Kumar Purushothaman Nov 19 '20 at 10:58
  • @PraveenKumarPurushothaman — No, it's the same in React. – Quentin Nov 19 '20 at 11:01
  • 1
    @PraveenKumarPurushothaman if it isn't exact the same issue, then why is your explanation solving exactly the same problem? `this` is determined at call time. If you don't do something about it (like binding) you will lose it when the method fires. You claim that the "new way" is to use arrow functions but that's still literally the same thing - it's just another way of preserving the context at call time. – VLAZ Nov 19 '20 at 11:01

3 Answers3

2

The changeColor method depends on this being the instance of the component (so that when it accesses this.state it can find it).

You are passing a function to the event listener so it used as a callback.

See How to access the correct this inside a callback?.

If you don't bind the this value, it will get called in the context of the DOM element when the event handler fires.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • This does clear my confusion a little bit . but does that mean 'this' inside a class component refers to the class component since it logs 'Toggle { context: undefined } ' ? – mahaveer jeevagan Nov 19 '20 at 11:22
  • See [How does the “this” keyword work?](https://stackoverflow.com/q/3127429). `this` inside a constructor function refers to the instance being constructed. – Quentin Nov 19 '20 at 11:24
0

This is an old way of doing things. If you don't bind, you won't get to use methods like the following inside the member custom methods like your changeColor():

this.setState();
this.props.*;
this.state.*;

And so on. But the new way of declaring things are using () => {} arrow functions.

Your same code can be rewritten using this way:

class Toggle extends React.Component {
  state = { color: green };

  changeColor = () => {
    const newColor = this.state.color == green ? yellow : green;
    this.setState({ color: newColor });
  };
  render() {
    return (
      <div style={{ background: this.state.color }}>
        <h1>Change my color</h1>
        <button onClick={this.changeColor}>Change color</button>
      </div>
    );
  }
}

This way, you don't need a constructor() or binding this to functions! To do another reality check, please try this:

import React, { Component } from "react";

export default class App extends Component {
  NoArrowFunction() {
    console.log(this);
  }
  ArrowFunction = () => {
    console.log(this);
  };
  render() {
    return <div>Check the Console!</div>;
  }
}
Praveen Kumar Purushothaman
  • 164,888
  • 24
  • 203
  • 252
0

this should refer to the scope or context of its use. In your case, it's referring to your Component.

If 'this' is undefined , what are we binding?

Then, you're binding undefined.

To put it simply, you need this to access your Component's properties inside your event handler. If you don't need to access them, then you don't need to bind this.

Consider the following case;

var obj = {
    name: 'My Object',
    myFunc: function() {
        console.log('This object name is', this.name);
    }
};

// When `this` is the `obj` itself.
obj.myFunc(); // Prints - "This object name is My Object"

// But, what if the function gets assigned to another variable / context? Which is what event listener does.
var anotherFunc = obj.myFunc;
anotherFunc(); // Prints - "This object name is"

// Since the function will print ANY context.name, we can also do it like;
var anotherFuncButBound = obj.myFunc.bind({
    name: 'Something else'
});
anotherFuncButBound(); // Prints - "This object name is Something else"

// In your case, you're doing the following;
var anotherFunc = obj.myFunc.bind(obj);
Dharman
  • 30,962
  • 25
  • 85
  • 135
choz
  • 17,242
  • 4
  • 53
  • 73