What is the difference between func() => {} and func = () => {} in class?

Viewed 90

I'm learning to use Class syntax now to create React components now and notice I now have to declare methods like this:

class Foo extends React.Component {
    ...
    bar = () => {
        this.setState({ ... })
    }    
}

instead of like this:

class Foo extends React.Component {
    ...
    bar() {
        this.setState({ ... })  // won't work
    }
}

or I can't use this.setState().

Can anybody explain what's the difference between creating methods like this and how they are related to the function prototype?

2 Answers

The first is relying on class fields, which aren't yet part of the language although they're a Stage 3 proposal and likely to be adopted soon. That code is setting a property on the instance (as though it were in the constructor) which is an arrow function (and thus closes over this). It's equivalent to this:

class Foo extends React.component {
    constructor() {
        this.bar = () => {
            this.setState({ ... })
        };
    }
}

The second is method syntax, which creates a property on the prototype object that gets used as the prototype of new instances, and which is a "normal" function in terms of this (e.g., what this is inside it depends on how it's called).

The difference between them in terms of this handling is significant: It means that if you use bar as a prop, with the first example you don't have to worry about this management (but you're creating a new function for every instance); with the method syntax, you do have to worry about this management (which also can end up creating a new function, depending on how you handle it).

If you're going to be using this style:

class Foo extends React.component {
    ...
    bar() {
        this.setState({ ... })  // won't work
    }
}

You'd need to bind this to the current context, like this:

class Foo extends React.component {
    constructor(props) {
       super(props);
       this.bar = this.bar.bind(this);
    }

    bar() {
        this.setState({ ... })  // works
    }
}
Related