Polina Shchukina
Polina Shchukina

Reputation: 65

this.setState in setTimeout in react

Function to update state:

animate() {
 setInterval(function(){
   setTimeout( this.setState({
     a: '123'
   }), 1000);
 }, 4000);
}

The method called:

componentDidMount() {
  this.animate();
}

Error:

Uncaught TypeError: this.setState is not a function

Then the next code tried:

animate() {
 setInterval(function(){
   setTimeout( () => {this.setState({
     a: '123'
   })}, 1000);
 }, 4000);
}

And the next error was:

Uncaught TypeError: _this2.setState is not a function

Upvotes: 4

Views: 2212

Answers (2)

Radu Szasz
Radu Szasz

Reputation: 1021

Although the answer submitted by m_callens is the proper one, I'll add this possibility using bind as well, for those who use pre-ES6 JavaScript.

animate() {
    setInterval((function(){
        setTimeout((function() {this.setState({
            a: '123'
        })}).bind(this), 1000);
    }).bind(this), 4000);
}

Upvotes: 1

m_callens
m_callens

Reputation: 6360

The problem stems from your definition of setInterval.

When you do setInterval(function() {...}), the this keyword is no longer bound to the React component but to the function it is called within because of the introduction of the new scope.

You can either switch it to:

animate() {
  const self = this

  setInterval(function() {
    setTimeout(() => self.setState({ a: '123' }), 1000)
  }, 4000)
}

This way self is assign to the React component value of this before the new scope is introduced, or you can use all arrow functions to preserve the this keyword referencing the component:

animate() {
  setInterval(() => {
    setTimeout(() => this.setState({ a: '123' }), 1000)
  }, 4000)
}

Upvotes: 4

Related Questions