Search code examples
reactjsbabeljsecmascript-next

React Uncaught TypeError: this.setState is not a function


I'm using property initializers. This is my state.

 state = {
 status: 'Simon Says!',
 compArr: [],
 color: 'red',
 userArr: []
};

This is my pen.

I call the state here

game = (event) => {
 let compArr = this.state.compArr;
 for (let i = 0; i < compArr.length; i++) {
  (function(i) {
    setTimeout(function() {
      switch (compArr[i]) {
        case 1:
          this.setState({
            color: 'green'
          });
          break;
        case 2:
          this.setState({
            color: 'red'
          });
          break;
        case 3:
          this.setState({
            color: 'yellow'
          });
          break;
        case 4:
          this.setState({
            color: 'blue'
          });
          break;
      }
    }, 1000 * i);
  }(i))
}
};

I get the following error

Uncaught TypeError: this.setState is not a function

How do I fix this in ES2015+?


Solution

  • The problem is that this doesn't refer to the correct context inside the setTimeout function ,you can do it the follwoing way

    game = (event) => {
     var self = this;
     let compArr = this.state.compArr;
     for (let i = 0; i < compArr.length; i++) {
      (function(i) {
        setTimeout(function() {
          switch (compArr[i]) {
            case 1:
              self.setState({
                color: 'green'
              });
              break;
            case 2:
              self.setState({
                color: 'red'
              });
              break;
            case 3:
              self.setState({
                color: 'yellow'
              });
              break;
            case 4:
              self.setState({
                color: 'blue'
              });
              break;
          }
        }, 1000 * i);
      }(i))
    }
    };
    

    CODEPEN

    You can simplyfy your logic by using an array

    game = (event) => {
     var self = this;
     let compArr = this.state.compArr;
     var color = ["green", "red", "yellow", "blue"];
     for (let i = 0; i < compArr.length; i++) {
      (function(i) {
        setTimeout(function() {
          self.setState({color: color[compArr[i] - 1]});
        }, 1000 * i);
      }(i))
    }
    };