5

Say I have a function in the Parent component that I want to use as a callback for the Child component. Which way is better?

render() {
    return (
        <Child handleClick={this.handleClick.bind(this)} />
    )
}

or

constructor() {
    super();
    this.handleClick = this.handleClick.bind(this);
}

According to this eslint, it is much better to do so in the constructor because the render() method may be called multiple times. This makes perfect sense to me.

However, this just means that the bound function ends up being a property on each and every instance. Thus defeating the entire purpose of the prototype.

I do know about the property initializers:

handleClick = () => {
    // do stuff
}

But it looks this syntax is no where close to being agreed upon for ES2017 (or whatever the next one might be). For this reason, I'm afraid to use this syntax as it might never make it into the language.

So, having said all that, what is the best way to go about this?

halfer
  • 19,824
  • 17
  • 99
  • 186
gjvatsalya
  • 1,129
  • 13
  • 29
  • 1
    I found another alternative.. doesn't get the exactly same result but works to... onClick={(event)=>this.handleClick(event)} – Lucas Katayama Nov 30 '16 at 00:49
  • @LucasKatayama But this is the same issue that the eslint that I had linked to was talking about, right? If we use bind or a fat arrow function, that will create a new function every time the render() method gets called. – gjvatsalya Nov 30 '16 at 00:54
  • Like I said... It is just another alternative to write the same think... For performance purposes I think the constructor is the right way... – Lucas Katayama Nov 30 '16 at 00:56
  • Ah okay, I get what you're saying. – gjvatsalya Nov 30 '16 at 00:57
  • It's the same way to think about prototype ... One declaration to avoid memory consumption... – Lucas Katayama Nov 30 '16 at 00:57
  • Here is another Stage-0 sugar, ` – yadhu Nov 30 '16 at 01:29

1 Answers1

4

Although all options you and other people in comments have said do definitely work, I would go for Airbnb's React styleguide one:

✓ Binding on the constructor

constructor(props) {
  super(props);
  this.foo = this.foo.bind(this);
}

✓ ES7 binding on constructor is also a good option (though keep in mind that it is still a proposal)

constructor(props) {
  super(props);
  this.foo = ::this.foo;
}

What about the other options?

✖ Binding on render

render() {
  return <button onClick={this.handleClick.bind(this}>...</button>
}

Rebinded on every re-render, not to say that if you have two elements that use the same function, you will have to choose whether to leave one without binding or binding both (which would be ugly or more inefficient).

✖ Arrow function (not binding)

render() {
  return <button onClick={(e) => this.handleClick(e)}>...</button>
}

You are going through one more function when there is no need to.

zurfyx
  • 31,043
  • 20
  • 111
  • 145
  • You don't just go through one more function! Using either `bind` or arrow function here causes the `onClick` property to change every render which means that the state changes, which means that next render, every single such item will be re-rendered. This is mostly a problem when the items are part of a list. https://stackoverflow.com/questions/36677733/why-shouldnt-jsx-props-use-arrow-functions-or-bind – hippietrail Sep 26 '17 at 04:20
  • The world has moved ahead of class-based components. Please suggest a solution for functional components. – backslashN Jul 11 '23 at 10:22