0

I am new to JavaScript and coming not forth with my current issue. I have here an React App and I try to expand it by a timer functionality. I created a timer (similar to this question: setInterval in a React app) and the timer functionality itself is working.

But the timer callback (or more exactly the setInterval callback) is not working. In the setInterval the variable this is pointing to Windows but I thought it should point to App, which is the class/object who created the timer and contains the setInterval callback. Therefore I get following error.

enter image description here

Here are the crucial code changes I made:

class App extends Component {

  //...

  componentDidMount() {

    //...

    var intervalId = setInterval(this.timer, 5000);
    // store intervalId in the state so it can be accessed later:
    this.setState({intervalId: intervalId});
  }

  componentWillUnmount() {
    
    //...

    // use intervalId from the state to clear the interval
    clearInterval(this.state.intervalId);
  }

  timer() {
    for (let i = 0; i < this.state.whitelist.length; i++) {
      this.requestDeviceStatus(this.state.whitelist[i]);
    }
  }

 //...

}

But you can access the complete source code/commit here: https://github.com/wewa00/Reacticz/blob/backgroundtimer/src/App.js, (And this are the Relevant commits: 02e3e93, 6bcabba.)

Why this pointing to Window and how can I access App from within timer()?

wewa
  • 1,628
  • 1
  • 16
  • 35

2 Answers2

1

TypeError

Use timer function with ES6 arrow method.

timer=()=>{
   for (let i = 0; i < this.state.whitelist.length; i++) {
        this.requestDeviceStatus(this.state.whitelist[i]);
    }
}
wewa
  • 1,628
  • 1
  • 16
  • 35
prasanth
  • 22,145
  • 4
  • 29
  • 53
  • Thank you for that hint. You were really fast with your answer. I had a mistake and corrected this like you stated. But the issue is still here, as you can see in the updated question. – wewa Jan 23 '21 at 14:24
  • check my updated answer. why i suggest `=>` instead of bind. we no need have remember to put bind each function inside the constructor. it something crowd in constructor – prasanth Jan 23 '21 at 14:31
  • I did not really understand this. But with your suggestion `this: App` in the `Scope` of `timer()`. – wewa Jan 23 '21 at 14:33
  • `this` target the class scope. if you are using `time()` like without `bind(this)` like @Prime answer. `this` will may not working. for same if you using `ES6` method like `=>` function its will allow parent scope this inside the `timer()` function – prasanth Jan 23 '21 at 14:50
0

You need to use bind to access App inside timer function.

class App extends Component {

  //...

  componentDidMount() {

    //...

    var intervalId = setInterval(this.timer, 5000);
    // store intervalId in the state so it can be accessed later:
    this.setState({intervalId: intervalId});
    this.timer = this.timer.bind(this); // <------------------------------
  }

  componentWillUnmount() {
    
    //...

    // use intervalId from the state to clear the interval
    clearInterval(this.state.intervalId);
  }

  timer() {
    for (let i = 0; i < this.state.whitelist.length; i++) {
      this.requestDeviceStatus(this.state.whitelist[i]);
    }
  }

 //...

}
Prime
  • 2,809
  • 1
  • 7
  • 23
  • I tried this out, but I still get the same error message. And when I debug my app, I can see, that `this: Window` in the `Scope` of `timer()`. – wewa Jan 23 '21 at 14:28