Hernan Ariel
Hernan Ariel

Reputation: 273

React: setting setInterval conditionally

My timer never stops after reaching zero (it keeps counting down on screen). I did a console.log on timer and I see that, while the time on screen is counting down, console.log returns that timer never actually changes its value. Any ideas why? Am I not setting state properly or something like that?

class Clock extends Component {
  constructor(props) {
    super(props);
    this.state = {break:5,
session:25,
timer: 1500}

  this.handleClick = this.handleClick.bind(this);
  this.handleTimer=this.handleTimer.bind(this);
   }

handleClick(event){
const id= event.target.id;
let breakvar= this.state.break;
let sessionvar= this.state.session;
if (id==="break-increment" && breakvar<=59){
this.setState((state) => ({
  break: this.state.break +1}));}

else if (id==="break-decrement" && breakvar>1){
this.setState((state) => ({
  break: this.state.break -1}));}

else if(id==="reset"){
this.setState((state) => ({
 break: 5, session: 25, timer: 1500}));  
}  


else if (id==="session-increment" && sessionvar <=59){
this.setState((state) => ({
session: this.state.session +1, timer: this.state.timer + 60}));}

else if(id==="session-decrement" && sessionvar>1){
this.setState((state) => ({
  session: this.state.session -1, timer:this.state.timer - 60}));}

}

handleTimer(evt){
let timer=this.state.timer;

let Interval=setInterval(() => { 
        this.setState({
            timer: this.state.timer - 1
        })
   console.log(timer) },1000)
if(timer ===0){
  clearInterval(Interval)
}
}





Clock(){
    let minutes = Math.floor(this.state.timer / 60);
    let seconds = this.state.timer - minutes * 60;
    seconds = seconds < 10 ? '0' + seconds : seconds;
    minutes = minutes < 10 ? '0' + minutes : minutes;
    return minutes + ':' + seconds;
}









render() {
    return(
            <div id="container">
                <Display break={this.state.break} displayTime={this.Clock()} session={this.state.session}/>
                <p id="break-label">Break length</p>
                <Button onClick={this.handleClick} id="break-increment"/>
                <Button onClick={this.handleClick} id="break-decrement"/>
                <p id="session-label">Session length</p>
                <Button onClick={this.handleClick} id="session-increment" />
                <Button onClick={this.handleClick} id="session-decrement"/>
                <Button onClick={this.handleTimer} id="start_stop"/>
                <Button onClick={this.handleClick} id="reset"/>
            </div>
)

}

Upvotes: 3

Views: 4017

Answers (1)

xadm
xadm

Reputation: 8418

This is a 'structural problem'.

You're checking condition in handler only once, not inside 'child function' invoked every second.

You need to move 'actions'/condition into 'interval body fn', sth like:

handleTimer(evt){
  clearInterval(this.Interval)
  this.Interval=setInterval(() => { 
    let timer=this.state.timer;
    if(timer > 0){
      this.setState({
        timer: this.state.timer - 1
      })
    }else{
      clearInterval(this.Interval)}
  },1000)}
}

Upvotes: 4

Related Questions