Search code examples
javascriptreactjssetstate

In React i'm getting this.setState is not a function error within setTimeout/setInterval


I've seen a few topics on the issue 'this.setState is not a function', but none have fixed it for me. I've used arrow functions or binding 'this', but still getting the error. The initial attempt is below. It uses nested setTimeout functions (i can explain why if it would help), but the issue is around this.setState.

Without looking into the 'useEffect' Hook, could i check whether i'm missing something basic/fundamental to setting state in React in the code below?

let delay = 5000;
      var startTime = new Date().getTime();

      let intervalTimerId = setTimeout(function request() {

        // first apply a random number to a div
        let randomNum = Math.floor(Math.random() * 6) + 1;
        // document.querySelectorAll(".someClass"+randomNum)[0].setAttribute("id", "test");

        // then after a second, remove the class
        setTimeout(() => {
          // document.querySelectorAll(".someClass"+randomNum)[0].setAttribute("id", "");

          // after another second, set state to use later
          setTimeout(() => {
            this.setState({someState: "testing"});
          }, 1000)

        }, 1000)

        // set new delay time
        if (new Date().getTime() - startTime > 9000) {
          delay = 3000;
        }

        console.log(new Date().getTime() - startTime)

        intervalTimerId = setTimeout(request, delay);

      }, delay);

Solution

  • You can try to use arrow function

    let delay = 5000;
    var startTime = new Date().getTime();
    
    const request = () => {
      // first apply a random number to a div
      let randomNum = Math.floor(Math.random() * 6) + 1;
      // document.querySelectorAll(".someClass"+randomNum)[0].setAttribute("id", "test");
    
      // then after a second, remove the class
      setTimeout(() => {
        // document.querySelectorAll(".someClass"+randomNum)[0].setAttribute("id", "");
    
        // after another second, set state to use later
        setTimeout(() => {
          this.setState({ someState: 'testing' });
        }, 1000);
      }, 1000);
    
      // set new delay time
      if (new Date().getTime() - startTime > 9000) {
        delay = 3000;
      }
    
      console.log(new Date().getTime() - startTime);
    
      intervalTimerId = setTimeout(request, delay);
    };
    
    let intervalTimerId = setTimeout(request, delay);