This is the third post of series in which we are going to explore the usage of React with ECMAScript6 and ECMAScript7.

You could find links to all parts of series below:

The code corresponding to this article is available at GitHub.

Update from 18.06.2016: Updated the code and text to use React 15 and Babel 6.

React Logo JavaScript Logo

If you look at paragraph “CartItem render method” of the previous article in the series you might be confused by the usage of {this.increaseQty.bind(this)}.

If we try the same example with just {this.increaseQty} we’ll see Uncaught TypeError: Cannot read property 'setState' of undefined in browser console:

Browser console with error

This is because when we call a function in that way binding to this is not a class itself, it’s undefined. It’s default JavaScript behavior and is quite expected. In opposite to this, in case you use React.createClass() all the methods are autobinded to the instance of an object. Which might be counter-intuitive for some developers.

No autobinding was the decision of React team when they implemented support of ES6 classes for React components. You could find out more about reasons for doing so in this blog post.

Let’s now see various ways of how to call class methods from your JSX in case you use ES6 classes. All the different methods we consider here are available at this GitHub repository.

Method 1. Using of Function.prototype.bind().

We’ve already seen this:

export default class CartItem extends React.Component {
    render() {
        <button onClick={this.increaseQty.bind(this)} className="button success">+</button>
    }
}

As any method of ES6 class is plain JavaScript function it inherits bind() from Function prototype. So now when we call increaseQty() inside JSX, this will point to our class instance. You could read more about Function.prototype.bind() in this MDN article.

Method 2. Using function defined in constructor.

This method is a mix of the previous one with usage of class constructor function:

export default class CartItem extends React.Component {
    
    constructor(props) {
        super(props);
        this.increaseQty = this.increaseQty.bind(this);
    }

    render() {
        <button onClick={this.increaseQty} className="button success">+</button>
    }
}

You don’t have to use bind() inside your JSX anymore, but this comes with the cost of increasing the size of constructor code.

Method 3. Using fat arrow function and constructor.

ES6 fat arrow functions preserve this context when they are called. We could use this feature and redefine increaseQty() inside constructor in the following way:

export default class CartItem extends React.Component {
    
    constructor(props) {
        super(props);
        this._increaseQty = () => this.increaseQty();
    }

    render() {
        <button onClick={_this.increaseQty} className="button success">+</button>
    }
}

Method 4. Using fat arrow function and ES2015+ class properties.

Additionally, you could use fat arrow function in combination with experimental ES2015+ class properties syntax:

export default class CartItem extends React.Component {
      
    increaseQty = () => this.increaseQty();

    render() {
        <button onClick={this.increaseQty} className="button success">+</button>
    }
}

So, instead of defining our class method in a constructor as in method number 3, we use property initializer.

Warning: Class properties are not yet part of current JavaScript standard. But your are free to use them in Babel using corresponding experimental flag (stage 0 in our case). Your could read more about how to do this in Babel documentation.

We’ve already switched to stage 0 in React and ES6 - Part 2, React Classes and ES7 Property Initializers, so this is not an issue for our example.

Method 5. Using ES2015+ function bind syntax.

Quite recently Babel introduced syntactic sugar for Function.prototype.bind() with the usage of ::. I won’t go into details of how it works here. Other guys already have done the pretty good explanation. You could refer to this official Babel blog post for more details.

Below is code with usage of ES2015+ function bind syntax:

export default class CartItem extends React.Component {
    
    constructor(props) {
        super(props);
        this.increaseQty = ::this.increaseQty;
        // line above is an equivalent to this.increaseQty = this.increaseQty.bind(this);
    }

    render() {
        <button onClick={this.increaseQty} className="button success">+</button>
    }
}

Again, this feature is highly experimental. Use it at your own risk.

Method 6. Using ES2015+ Function Bind Syntax in-place.

You also have a possibility to use ES2015+ function bind syntax directly in your JSX without touching constructor. It will look like:

export default class CartItem extends React.Component {
    render() {
        <button onClick={::this.increaseQty} className="button success">+</button>
    }
}

Very concise, the only drawback is that this function will be re-created on each subsequent render of the component. This is not optimal. What is more important that will cause problems if you use something like PureRenderMixin (or its equivalent for ES2015 classes).

Conclusion

In this article, we’ve discovered various possibilities of binding class methods of React components. I’ve prepared test project based on code from part 2 of this series. It’s available here.

Next time we’ll see what is the state of React mixins for ES2015 classes.

Further Reading