4

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?

kevguy
  • 4,328
  • 1
  • 24
  • 45
  • @ShubhamKhatri This question is not a duplicate because what I'm asking is different in essence. I'm essentially asking the difference between using the two different kinds of syntax in a JavaScript `class`, and what I want to know is how they work on `function prototypes`. I only noticed it when I'm using React and I'm not even asking anything about React or any handling. Please unduplicate it, you haven't even checked out what I'm asking here and the solutions below. – kevguy Nov 17 '17 at 11:04
  • Sure, While the question may not be an exact duplicate of the one I marked, but it sure answers a part of your question as why this.setState won't work. but yes it doesn't answer the function prototype question. https://stackoverflow.com/questions/41278385/updated-state-not-reflecting-after-setstate/41278440#41278440 – Shubham Khatri Nov 17 '17 at 11:07
  • Related: [Difference between nameFunction() {} and nameFunction () => {} in ECMA6](https://stackoverflow.com/q/38296733/4642212). – Sebastian Simon Aug 04 '19 at 15:32

2 Answers2

8

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

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • So if I use `function` syntax instead, `bar = function() { this.setState({ ... }) }`, there will be no difference in terms of the context, especially `this`? – kevguy Nov 17 '17 at 10:32
  • @kevguy: If you used a `function` function, `this` would be just like it is with method syntax, but the function would be on the instance (a different function for each instance) instead of on the object used as the prototype of instances (one function shared amongst all instances). – T.J. Crowder Nov 18 '17 at 10:41
0

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
    }
}
codejockie
  • 9,020
  • 4
  • 40
  • 46