Ad

Getting This.startBreak() Is Not A Function Error In React.js

- 1 answer

I'm a newbie working on a pomodoro timer app in react and I'm getting this error after calling a function within setInterval():

TypeError: this.startBreak is not a function

Surely it's something trivial so I'll be grateful for any advice. Here's the code:

startSession = () => {

let sessionSecondsTotal = (this.state.hours * 60 * 60) + (this.state.minutes * 60) + (this.state.seconds);
let hoursNode = document.getElementById("hours");
let minutesNode = document.getElementById("minutes");
let secondsNode = document.getElementById("seconds");



let hoursShow = this.state.hours;
let minutesShow = this.state.minutes;
let secondsShow = this.state.seconds;


setInterval(function(){                                         
      secondsShow = secondsShow - 1;
      if(secondsShow <= 0){
          secondsShow = 59;
          minutesShow = minutesShow - 1;
      }else if(hoursShow > 0){
        if(minutesShow <= 0){
          hoursShow = hoursShow - 1;
          minutesShow = 59;
        }
      }

      hoursNode.textContent = hoursShow.toString();
      minutesNode.textContent = minutesShow.toString();
      secondsNode.textContent = secondsShow.toString();

      sessionSecondsTotal = sessionSecondsTotal - 1;

      if(sessionSecondsTotal === 0){
        this.startBreak();
      }

  },1000)
}
Ad

Answer

When you define a function(){} in javascript a new context (this) will be created. You can read more about contexts here

There are many ways to handle it:

1) Save your previous context to variable and use it inside new function

let hoursShow = this.state.hours;
let minutesShow = this.state.minutes;
let secondsShow = this.state.seconds;
const self = this;


setInterval(function(){                                         
      secondsShow = secondsShow - 1;
      if(secondsShow <= 0){
          secondsShow = 59;
          minutesShow = minutesShow - 1;
      }else if(hoursShow > 0){
        if(minutesShow <= 0){
          hoursShow = hoursShow - 1;
          minutesShow = 59;
        }
      }

      hoursNode.textContent = hoursShow.toString();
      minutesNode.textContent = minutesShow.toString();
      secondsNode.textContent = secondsShow.toString();

      sessionSecondsTotal = sessionSecondsTotal - 1;

      if(sessionSecondsTotal === 0){
        self.startBreak();
      }

  },1000)
}

2) Use arrow function, because it will use context from upper scope

let hoursShow = this.state.hours;
let minutesShow = this.state.minutes;
let secondsShow = this.state.seconds;


setInterval(() => {                                         
      secondsShow = secondsShow - 1;
      if(secondsShow <= 0){
          secondsShow = 59;
          minutesShow = minutesShow - 1;
      }else if(hoursShow > 0){
        if(minutesShow <= 0){
          hoursShow = hoursShow - 1;
          minutesShow = 59;
        }
      }

      hoursNode.textContent = hoursShow.toString();
      minutesNode.textContent = minutesShow.toString();
      secondsNode.textContent = secondsShow.toString();

      sessionSecondsTotal = sessionSecondsTotal - 1;

      if(sessionSecondsTotal === 0){
        this.startBreak();
      }

  },1000)
}

3) Bind context to the new function

let hoursShow = this.state.hours;
let minutesShow = this.state.minutes;
let secondsShow = this.state.seconds;


setInterval((function(){                                         
      secondsShow = secondsShow - 1;
      if(secondsShow <= 0){
          secondsShow = 59;
          minutesShow = minutesShow - 1;
      }else if(hoursShow > 0){
        if(minutesShow <= 0){
          hoursShow = hoursShow - 1;
          minutesShow = 59;
        }
      }

      hoursNode.textContent = hoursShow.toString();
      minutesNode.textContent = minutesShow.toString();
      secondsNode.textContent = secondsShow.toString();

      sessionSecondsTotal = sessionSecondsTotal - 1;

      if(sessionSecondsTotal === 0){
        this.startBreak();
      }

  }).bind(this),1000)
}
Ad
source: stackoverflow.com
Ad