loading...
Cover image for React Quick Tip: Use Class Properties and Arrow Functions to Avoid Binding `this` to Methods

React Quick Tip: Use Class Properties and Arrow Functions to Avoid Binding `this` to Methods

davejs profile image David Leger ・1 min read

When you want to access this inside a class methods of your React component, you need to bind it to your method:

class Button extends Component {
  constructor(props) {
    super(props);
    this.state = { clicked: false };
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick() {
    this.props.setState({ clicked: true });
  }
  render() {
    return <button onClick={this.handleClick}>Click Me!</button>;
  }
}

Binding this to handleClick in the constructor allows us to use this.setState from Component inside handleClick. Without this binding, this is re-scoped for handleClick and loses context of the component’s setState method.

But this is completely unnecessary, extra code!

You can clean up this ugliness by using some new ES6+ features. Here is the same component, rewritten using class properties and arrow functions to avoid binding this to handleClick:

class Button extends Component {
  state = { clicked: false };
  handleClick = () => this.setState({ clicked: true });
  render() {
    return <button onClick={this.handleClick}>Click Me!</button>;
  }
}

Note: You must have transform-class-properties enabled in your own Babel config in order to use class properties. If you’re using Create React App, this is already enabled for you.

Why Does This Work?

This works because of two reasons:

  1. Arrow functions, by their nature, do not re-scope this, so we don’t need to bind this in the class constructor.
  2. JavaScript has first-class functions, meaning functions are treated the same as data. So arrow functions can be assigned to variables, or in this case, to class properties.

Bonus Tip

Notice in the second example, I defined state as a class property as well, negating the need for a constructor.

Posted on by:

davejs profile

David Leger

@davejs

Frontend developer passionate about creating things that help people live happier lives.

Discussion

pic
Editor guide
 

I prefer to do this:

return <button onClick={(() => this.handleClick())}>Click Me!</button>;
 

Nice! Yes, that certainly works depending on the the use case. This approach works because render() is bound to this of the class by React.

Keep in mind however that you'll have a (rather small) performance hit because the onClick function is being initialized every time render is invoked since that is where it is being defined.

 

Well, I am not sure if such a thing can be called a "performance hit" since we are talking basically of 1 line of code, and there are plenty of those that run every time the render starts. The complexity of the operation is not even exponential but linear. I don't think that there is any performance concern to worry about in this case.

Enrique, I am afraid there really is a performance hit. Not because you are creating an arrow function on the fly - as you say, that's mostly irrelevant-, but because a new function will be passed as a prop and the component will re-render (needlessly).

If this happens with a button, that's not a problem, but more complex components will noticeably slow down your apps. This is a known caveat, you'll find many references in the web (for example: github.com/yannickcr/eslint-plugin...)