mahaveer jeevagan
mahaveer jeevagan

Reputation: 59

why are we binding 'this' keyword for event handlers in react class components?

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 ?

Upvotes: 1

Views: 279

Answers (3)

choz
choz

Reputation: 17858

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);

Upvotes: 0

Quentin
Quentin

Reputation: 943564

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.

Upvotes: 2

Praveen Kumar Purushothaman
Praveen Kumar Purushothaman

Reputation: 167182

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>;
  }
}

Upvotes: 0

Related Questions