Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Issue accessing state inside setInterval in React.js

Tags:

I am trying to access the state of a component inside a setInterval in this way but it's not working:

componentDidMount: function() {
    setInterval(function() {
      console.log(this.state);
    }, 3000);
}

However, if I place the callback function in a separate component method, it works perfectly:

displayState: function() {
  console.log(this.state)
}
componentDidMount: function() {
    setInterval(this.displayState(), 3000);
}

Any idea why is this happening? I would prefer to use the first option.

like image 380
danst_18 Avatar asked Oct 13 '14 20:10

danst_18


People also ask

Does setInterval work in React?

Using setInterval lets you execute a function at specific intervals. It's often very useful in React apps, for example for checking a condition regularly or fetching data every so often.

How do you call setInterval in React?

Run setInterval() from a React button onClick event To stop the interval with a button click, you need to save the interval ID returned by the setInterval() method as a state value. Next, modify the handleClick() function and add an if block that checks for the intervalId value first.

How do you clean up setInterval in React?

Clearing setInterval in React To stop an interval, you can use the clearInterval() method. ... useEffect(() => { const interval = setInterval(() => { setSeconds(seconds => seconds + 1); }, 1000); return () => clearInterval(interval); }, []); ... What is this?


2 Answers

In your first example, this is out of scope when the callback function fires. One way to solve this problem would be to use a variable:

componentDidMount: function() {
    var self = this;
    setInterval(function() {
      console.log(self.state);
    }, 3000);
}

The problem with your second attempt is that you are calling the function immediately and passing the result of executing the function to setInterval. You should pass the function itself, taking care to bind the value of this:

componentDidMount: function() {
    setInterval(this.displayState.bind(this), 3000);
}

To clarify, the difference between this approach and the second example in your question is that here, a function is being passed to setInterval (because function.bind() returns a function).

As you are using React.createClass, it is not necessary to manage the binding of this yourself, due to autobind. This means that you can just pass the function itself and this will be the same as in the original context:

componentDidMount: function() {
    setInterval(this.displayState, 3000);
}

Of course, the most suitable approach depends on whether you prefer to use an anonymous function or not.

like image 188
Tom Fenech Avatar answered Sep 18 '22 16:09

Tom Fenech


You need to execute the interval handler with the correct reference to this. Use React’s autobinding for the cleasest solution IMO:

displayState: function() {
  console.log(this.state)
},
componentDidMount: function() {
    setInterval(this.displayState, 3000)
}

Or use bind if you want an anonymous function:

componentDidMount: function() {
    setInterval(function() {
        console.log(this.state)
    }.bind(this), 3000)
}
like image 23
David Hellsing Avatar answered Sep 18 '22 16:09

David Hellsing