ciaoben
ciaoben

Reputation: 3338

It is better bind methods in the constructor of a component or in the render method?

Which is better (more performant), if one it is:

A:

class Man extends React.Component {
  constructor(props) {
    super(props)
    this.talk = this.talk.bind(this)
    this.state = {}
  }

  talk() { .. }

  render () {
    return <div onClick={this.talk}>talk!</div>
  }
}

B:

class Man extends React.Component {
  constructor(props) {
    super(props)
    this.state = {}
  }

  talk() { .. }

  render () {
    return <div onClick={this.talk.bind(this)}>talk!</div>
  }
}

C:

class Man extends React.Component {
  constructor(props) {
    super(props)
    this.state = {}
  }

  talk() { .. }

  render () {
    return <div onClick={() => this.talk()}>talk!</div>
  }
}

I think that calling the bind method directly in the render method could be negligible, but after all the render method is called ton of times. I want to understand if making a change in a big codebase is it worth it or not.

Upvotes: 3

Views: 3541

Answers (4)

Jose Paredes
Jose Paredes

Reputation: 4080

The best solution will be auto binding internal methods. using arrow functions as methods.

So we don't rely on the constructor to bind the internal methods, and for example having multiple internal methods will just increase the number of lines of your files unnecessarily

Here is an implementation of what I'm saying:

class Man extends React.Component {
  constructor(props) {
    super(props)
    this.state = {};
  }

  talk = () => { .. }

  render () {
    return <div onClick={this.talk}>talk!</div>
  }
}

In order for this to work, you should use transform-class-properties from Babel Stage 2 preset

Upvotes: 3

Mayank Shukla
Mayank Shukla

Reputation: 104379

As per React DOC (last para of the page):

onClick={(e) => this.handleClick(e)} and onClick={this.talk.bind(this)}

The problem with this syntax is that a different callback is created each time the component renders. In most cases, this is fine. However, if this callback is passed as a prop to lower components, those components might do an extra re-rendering. We generally recommend binding in the constructor or using the property initializer syntax, to avoid this sort of performance problem.

MDN DOC:

Function.prototype.bind():

The bind() method creates a new function always.

Binding method in the constructor:

However if you bind the method in the constructor:

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

and use it like this:

onClick={this.handleClick}

It will create only one instance and use that instance always. So binding method in the constructor means you end up binding only once and you can re-use it as many times, even if the render() method is called multiple times the same function will be used.

property initilizer syntax (this is experimental syntax.):

By this way you don't need to bind all the methods in the constructor, and it will not create multiple callbacks also.

handleClick = () => {
   .....
}

Upvotes: 4

Ritesh Bansal
Ritesh Bansal

Reputation: 3238

I think you should do binding in constructor as calling bind returns a new function. It should be called one time for performance reasons. In you call it in render, bind will be called on every render and will return a new reference each time.

Upvotes: 0

Pineda
Pineda

Reputation: 7593

If we are to define 'more performant' as something that requires the least amount of computational resource, then option A (binding in the constructor) would be the most performant.

As you state, this is because this only happens once during the creation of an instance of the component. The .bind returns a newly bound function which is referenced later on.

The latter two options will be creating new functions (bound or anonymous) on every render, which is not necessary in this context.

Upvotes: 1

Related Questions