2

In the React docs page on handling events, it says:

Generally, if you refer to a method without () after it, such as onClick={this.handleClick}, you should bind that method.

I'm not clear on the difference between onClick={this.handleClick} and onClick={this.handleClick()} or why using the () means you wouldn't need to bind this.

Any help in understanding would be greatly appreciated.

Deja
  • 3,278
  • 2
  • 18
  • 46
  • 7
    The `()` mean that you want to immediately *call* the function and use whatever value it returns. – Pointy Apr 10 '19 at 21:34
  • 2
    Never use `onClick={this.handleClick()}`. It won't work (whether it binds `this` or not). Either use `onClick={this.handleClick.bind(this)}` or `onClick={e => this.handleClick(e)}`. To be clear: the advice from the docs does not suggest that you can use `this.handleClick()` nor that you don't have to bind `this` if you do that. Again, `onClick={this.handleClick()}` is always bad. – Chris G Apr 10 '19 at 21:43
  • I'm still confused because it seems like it's also called without the `()` (as long as `this` is bound). In an example on the Handling Events page I linked, `{this.handleClick}` seems to call the `handleClick()` method defined on the class. I don't see `handleClick()` anywhere. – Deja Apr 10 '19 at 21:55
  • 1
    This isn't specific to React, and doesn't really have anything to do with binding. Here's a plain JS example: https://jsfiddle.net/khrismuc/23nmurt4/ – Chris G Apr 10 '19 at 22:09
  • 1
    `I don't see handleClick() anywhere.` You assigned `this.handleClick` to `onClick`, so when React calls `element.onClick()`, that's when `this.handleClick()` gets called. – Chris G Apr 10 '19 at 22:38

2 Answers2

3

this.handleClick refers to a function. this.handleClick() calls that function.

It's not so much that using () removes the need for binding, it's just that in the context of calling this.handleClick() javacript "knows" what this should refer to.

So if I call:

this.handleClick(); 

It's clear from context what this was.

But if I call

const foo = this.handleClick;
foo();

I'm still calling the same function, but the original reference to this was gone.

As for 'why' that is. I don't know the historical reason for this, but it a side-effect of how Javascript was defined. The javascript language would probably be a little nicer if this was not the case, but this is how the language works. I'm not sure if this is a satisfying answer.

Evert
  • 75,014
  • 17
  • 95
  • 156
2

When affecting a function reference to a new variable, the context (refered by this inside that function) is not copied.

In the snippet below, the saysHi function uses this. The object it references changes depending on the way it's called or bound.

const jack = {
  name : 'Jack',
  saysHi : function() {
    console.log("Hi, I'm " + this.name);  
  }
};
jack.saysHi(); // this will reference jack

const someoneSaysHi = jack.saysHi;
someoneSaysHi(); // this will not reference jack anymore, but the global object window

const joe = { name : "Joe" };
const joeSaysHi = someoneSaysHi.bind(joe);
joeSaysHi(); // this will reference joe, because you bound the function to joe
  • By calling jack.saysHi(), this will be a reference to jack. I'm calling the function with the . operator, invoking it in the context of the jack object.
  • By setting const someoneSaysHi = jack.saysHi ; and then calling someoneSaysHi (), I'm calling it without any context. So this will be a reference to the global object window. That's a feature of the language.
  • By binding someoneSaysHi to the joe context, I'm creating a new function and in that function, the this will be a reference to joe.

More complete answer : How does the “this” keyword work?

Now, about about your issue :

Generally, if you refer to a method without () after it, such as onClick={this.handleClick}, you should bind that method.

The onClick attribute needs a function reference to attach to the click event.

  • onClick={this.handleClick()} will immediatly call this.handleClick (with the right context) and attach the click event to the returned value of the this.handleClick function.
  • onClick={this.handleClick} without binding anything will attach the the click event to the handleClick function, but in that context, the this inside your handleClick function will be the event's current target (the element you clicked on) - this is a feature of event handlers.
  • onClick={this.handleClick.bind(this)} will attach the click event to a new function reference bound to the object referenced by this.
Guillaume Georges
  • 3,688
  • 3
  • 11
  • 28