Understanding the need of bind()

Hello, everyone.
My question doesn’t really have anything to do with the lesson itself, but rather with this particular line of code:

this.handleClick = this.handleClick.bind(this);

As far as my knowledge about this goes, there are some situations where the value of this is lost. I do understand what this line of code does(kind of), but i’m trying to understand why this line of code was necessary in this particular scenario. Is it because of this line?

<button onClick={this.handleClick}>Click Me</button>

Does the line above transform behind the scenes into:

document.querySelector('button').addEventListener('click', this.handleClick);

so this does not reference the React component anymore, but references the button instead? Is this how it is?

  **Your code so far**

class MyComponent extends React.Component {
constructor(props) {
  super(props);
  this.state = {
    name: 'Initial State'
  };
  this.handleClick = this.handleClick.bind(this);
}
handleClick() {
  // Change code below this line
  this.setState({name: 'React Rocks!'});
  // Change code above this line
}
render() {
  return (
    <div>
      <button onClick={this.handleClick}>Click Me</button>
      <h1>{this.state.name}</h1>
    </div>
  );
}
};
  **Your browser information:**

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36 Edg/98.0.1108.43

Challenge: Set State with this.setState

Link to the challenge:

The problem is, handleClick() does not have this assigned to the component at all. Inside the constructor function we have access to the component “this”. Inside the render method we also have access to the proper “this”. But inside custom made methods, we dont. Their this by default is the window object(in the fcc interpreter its undefined). This is why we need to find way to pass the proper this to the custom method.
You can try this, before you bind this properly:

handleClick() {
  console.lot(this)
}

You will see, it will return undefined.
If you try to console.log(this), inside the render or constructor, they will prompt the component.

1 Like

Classes are being used.

When an object is created using a class constructor in JavaScript, it sets this to the context of that object.

So if you do this:

class MyComponent extends Component {
  state = {
    clicked: "Not clicked yet"
  }

  clickHandler() {
    this.setState({ clicked: "I got clicked" })
  }

  render() {
    return(
      <div>
        <p>{ this.state.clicked }</p>
        <MyOtherComponent clickHandler={this.clickHandler} />
      </div>
    )
  }
}

And MyOtherComponent is like this:

class MyOtherComponent extends Component {
  render()  {
    return <button onClick={this.props.clickHandler} />Click me</button>
  }
}

When MyOtherComponent initialises, this is an instance of MyOtherComponent. So this.setState in the clickHandler function it runs is going to try to set the state of MyOtherComponent, rather than the parent it was passed from.

By binding it in the parent, you are setting this to refer to MyComponent, kinda locking it in, then you can pass that bound function (bind creates a new function) down to another component safely, knowing it will affect the state of the component it was passed from. this inside that bound function refers to the instance of MyComponent it was created in.


Edit: just for clarity, you do not need to bind in the exact code you posted: it will work just fine without that. Everything is contained in that one object, so this will be what you expect it to be. However in one of the next few lessons, you will be asked to add another component and pass a handler function to it: it is setting things up for that.

Note for future reference that you don’t need to bind if you do this:

handleClick = () => {
  // Change code below this line
  this.setState({name: 'React Rocks!'});
  // Change code above this line
}
  • note the arrow function: this is a key reason why arrow functions exist in JS as they make many usecases of bind obselete
  • the syntax (class properties) was an addition to JS which appeared after the curriculum.was originally written, which is why it isn’t mentioned

Also note for future reference that most modern React code (as in most stuff written in the past four years or so), not using classes at all, doesn’t require binding anything. It’s specific to code using classes.

2 Likes

Thanks for making it a bit more clear. I’ll throw some console.log’s around, to see what’s going on.

You’re right. If i comment out this line:

this.handleClick = this.handleClick.bind(this);

and do this:

handleClick() {
  // Change code below this line
  console.log(this);
  // Change code above this line
}

the console.log(this) shows me undefined. On the flip side, it shows me the component, if the bind() is active. Is there any reason for things being like this?
I mean, why does this point to the component when inside the render and the constructor but not inside those other methods? Was React designed like this on purpose or is there some JavaScript flaw that prevented this from behaving properly inside custom methods and the React creators said 'meh, we’ll just use bind()'?

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.