Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ES6 React: Will ES.Next's @autobind bind methods only once for each instance?

There are a lot of questions/articles written on the numerous ways to handle binding in ES6 React, but most don't seem to address a problem outlined in the React docs (emphasis mine):

We recommend that you bind your event handlers in the constructor so they are only bound once for every instance:

constructor(props) {
  super(props);
  this.state = {count: props.initialCount};
  this.tick = this.tick.bind(this);
}

For context, they're advising against in-line binding of methods, such as:

//using .bind()
<div onClick={this.tick.bind(this)}>

// ES6 anon arrow functions
<div onClick={() => this.tick()}>

// ES.Next :: operator
<div onClick={::this.tick}>

Sure. But the recommended solution of binding every method in the constructor is cumbersome w/ a lot of methods, so I was looking at the ES.Next @autobind decorator at class level as a simple solution:

import { autobind } from 'core-decorators';

@autobind
class Person {
  getPerson() {
    return this;
  }

  getPersonAgain() {
    return this;
  }
}

let person = new Person();
let { getPerson, getPersonAgain } = person;

getPerson() === person;
// true

getPersonAgain() === person;
// true

What I can't figure out is: will this decorator have the same disadvantage of in-line binding methods? i.e., will the methods be bound just once for every instance?

If not, is there a succinct solution that avoids this pitfall?

like image 547
Brandon Avatar asked Mar 27 '26 17:03

Brandon


1 Answers

Class instance fields and their associated initializers solve the issue of having to assign properties with the same name as methods inside the constructor but with a more succinct syntax. The following example is possible with Babel's class properties transform:

class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {count: props.initialCount};
  }
  tick = () => {
    this.setState({count: this.state.count + 1});
  };
  ...
 }

This creates a new, bound tick property for each Counter instance. This creates the same number of bound functions as React.createClass did.

Without the instance field and initializer, the effect is the same (a bound tick property is created for each Counter instance) but with more verbose syntax:

constructor(props) {
  super(props);
  this.state = {count: props.initialCount};
  this.tick = this.tick.bind(this);
}
tick() {
  this.setState({count: this.state.count + 1});
}
like image 114
Ross Allen Avatar answered Mar 31 '26 03:03

Ross Allen



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!