0

I am new to React. I encountered a strange problem while I am following the "Quick Start" of React official page https://facebook.github.io/react/docs/state-and-lifecycle.html . You can try on CodePen here: http://codepen.io/gaearon/pen/amqdNA?editors=0010

In this code snippet

componentDidMount() {
    this.timerID = setInterval(
        () => this.tick(),
        1000
    );
}

it uses arrow function syntax to define a function which would be executed repeatedly, by passing the anonymous function object as the first argument of setInterval().

Since I am a curious guy, I tried several different ways to pass an "equivalent" function object as the first argument. But none of my ways works.

componentDidMount() {
    this.timerID = setInterval(
        this.tick, // This cannot work in CodePen

        //function () {
            //this.tick();
        //}, // No

        //function () {
            //return this.tick();
        //}, // No

        //() => this.tick(), // This is the official way that works
        //() => {this.tick();}, // This also works, but notice the difference between this and the last one 
        //() => {this.tick()}, // Also works
        //() => {return this.tick();}, // Also works, think it equivalent as official one
        1000
    );
}

I think in a pure Javascript code snippet, all these ways are valid for setInterval to work. Especially, as the official document (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions) says, the arrow function definition is generally equivalent to the function () { ... } definition. But they just seem not equivalent in React and Babel.

After I examined the compiled Javascript code by Babel, they differ by a _this2 object.

// Javascript compiled by Babel
Clock.prototype.componentDidMount = function componentDidMount() {
    var _this2 = this;

    this.timerID = setInterval(
        //this.tick // This is the compiled code using one of my way

        /*function () {
            this.tick();
        },*/ // This is another one

        function () {
            return _this2.tick();
        }, // This is the compiled code using the official way

        //function () {
            //_this2.tick();
        //}, // This is the compiled code of another working example
        1000
    );
};

So, I am asking, why must we use the arrow function syntax here? Why the equivalent ways does not get compiled correctly? Is this a bug of React or Babel?

EDIT:

OK. Thank you very much, guys! That tricky thing about "this" in Javascript almost answers every question I have. Now I know there is a big difference between () => {} definition and function () {} definition, and why Babel doesn't do what I expect.

But, this does not answer why this could not work

this.timerID = setInterval(
    this.tick, // This cannot work in CodePen
    1000
);

Could someone also take a look on this "easy" line of code? I guess it's not related to "this" in the same way?

3
  • 1
    Funktion(){} and ()=>{} are Not the same thing. The arrow function will keep its sourrounding context (this) and the normal function is declaring a new context for "this" Commented Feb 1, 2017 at 21:55
  • @cyrix Ah! This is really important! Commented Feb 1, 2017 at 22:07
  • stackoverflow.com/a/41970338/2902660 provides a little description how the context of a function (i.e. the value of this inside it's function definition) is evaluated Commented Feb 1, 2017 at 23:00

1 Answer 1

1

Function () {} and () =>{} are NOT the same thing.

Consider:

#1
function foo() { 
  console.log('foo');
}

vs:
#2
foo = () => { 
  console.log('foo')
}

Function #1 has a newly created context confined to the function, whereas function #2 doesn't create a new context this variable.

When Babel converts everything, I believe in order for function #2 to not have a new context it does something like this:

foo = () => {
  console.log(this.data);
}

Becomes

var this_2 = this;
function foo () {
  console.log(this_2.data);
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.