setInterval function without arrow function
Asked Answered
C

8

16

I am learning about react components following the documentation https://facebook.github.io/react/docs/state-and-lifecycle.html

Why do we need to use arrow function here:

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

Why can't I just say (obviously it doesn't work)

this.timerID = setInterval(this.tick(), 1000);
Club answered 20/8, 2017 at 9:26 Comment(1)
this.timerID = setInterval(function(){ this.tick() }.bind(this), 1000);Catch
C
11

The first argument for setInterval is of type function. If you write this:

this.timerID = setInterval(this.tick(), 1000);

…then you don't pass a function, instead you execute the function this.tick immediately and then pass the value returned by that function call as an argument.

You could write it like this:

this.timerID = setInterval(this.tick, 1000);

If you omit the parentheses, you pass a reference to your this.tick function, which is then executed by setInterval after 1000 milliseconds.

Chrissie answered 20/8, 2017 at 9:31 Comment(3)
That answer is wrong. You need to use binding if you want to avoid an arrow function, since tick() calls this.setState. If you don't, it returns 'this.setState is not a function`Birnbaum
Why an arrow function solves the binding issue? I would love to know aahahBirnbaum
Wrong, not workingTachyphylaxis
F
9

setInterval takes function as first argument, in the second case it is getting a returned value

Change it to

this.timerID = setInterval(this.tick.bind(this), 1000);

or

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

which is probably what you need when you want to bind the function to the React context.

See this answer on why you need to bind functions in React

If you don't you could have simply written

this.timerID = setInterval(this.tick, 1000);
Flaunty answered 20/8, 2017 at 9:29 Comment(0)
G
3

Why do we need to use arrow function here

Answer is simple : see the result inside live script example...

class Persons{

    scopeOne(){
          // your will see the result this will display our current object 'Persons'
          setInterval(function(){
          
              console.info(' SCOPE ONEo : '+this);
          
          },3000);    
    }
    scopeTwo(){
          setInterval(function(){
          
              console.info(' SCOPE TWO : '+this);
          
          }.bind(this) ,3000);
    }
    
    scopeThree(){
        setInterval(() => { console.info(' SCOPE THREE : '+this) },3000);
    }
}

let p = new Persons();
    p.scopeOne();
    p.scopeTwo();
    p.scopeThree();

in first scope the result is WINDOW OBJECT so we cannot access our current class scope so in 2nd scope we using scope with bind(this) that helps to bind our current object scope, and in third which do same as 2nd scope calling the current object....

Gyratory answered 1/6, 2020 at 16:49 Comment(0)
I
1

The simple answer to that is that the tick function needs to be able access the context of its use/ this, which is the Clock component. In other words it needs to be bound to the Clock component so that it works in the context of the Clock component and not the global context which is everything outside of the Clock component.

Functions within React classes are not bound by default and failure to bind the function will return undefined instead of the expected result.

There are several ways to bind the tick function to the Clock component example from the Reactjs website.

  1. Arrow functions can access this which is why they are used in the example. In other words, writing an arrow function implicitly means it binds its contents to the local context (the Clock component in this case). Read more on that in this Medium article

  2. Bind the tick function in the constructor

class Clock extends React.Component{
 constructor(props){
   super(props);
   this.state={date: new Date()}
   this.tick=this.tick.bind(this)
 }
  1. Bind the tick function in the setInterval method
 componentDidMount() {
    this.timerID = setInterval(this.tick.bind(this),
      1000
    );
  }
Isopropanol answered 28/11, 2020 at 5:42 Comment(0)
N
1

Transform a function called tick into a variable with an anonymous function, so you can pass it as an argument without parentheses.

Taking this code (https://codepen.io/gaearon/pen/amqdNr?editors=0010) as a base, you can update like this:

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

  tick = () => {
    this.setState({
      date: new Date()
    });
  }

Generally speaking, whenever you are going to pass a function as a parameter in js that uses an object variable, you need to BIND it with its object, so you don´t lose this reference. The two ways to do this are: using arrow functions or using bind().

Noto answered 23/9, 2022 at 0:34 Comment(0)
U
0

You need to supply a function reference, you are trying to invoke a function, unless that function returns a function reference, your code will not work

It should look like so

this.tick = function() { .... }

this.timerID = setInterval(this.tick, 1000);
Unemployable answered 20/8, 2017 at 9:31 Comment(0)
B
0

If you are not using arrow function then your code should look something like this:

this.timerID = setInterval(function(){ this.tick() }, 1000);
Buchheim answered 20/8, 2017 at 9:31 Comment(0)
P
-1

Technically, you should be able to use the second code snippet if this.tick() returns a function.

Powerboat answered 8/9, 2018 at 9:25 Comment(2)
Yes, but it would still not be equivalent to the first example, and this doesn't answer OPs question.Manolo
That's true. Apart from the previous answers given, do you think it might be due to "saving the this value"? Like the two snippets could have different this valuesPowerboat

© 2022 - 2024 — McMap. All rights reserved.