DEV Community

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

Posted on

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

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>;
  }
}
Enter fullscreen mode Exit fullscreen mode

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>;
  }
}
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (5)

Collapse
 
enriquemorenotent profile image
Enrique Moreno Tent • Edited

I prefer to do this:

return <button onClick={(() => this.handleClick())}>Click Me!</button>;
Enter fullscreen mode Exit fullscreen mode
Collapse
 
davejs profile image
David Leger

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.

Collapse
 
enriquemorenotent profile image
Enrique Moreno Tent

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.

Thread Thread
 
tokland profile image
Arnau Sanchez • Edited

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...)

Collapse
 
rkichenama profile image
Richard Kichenama