有条件地清除setInterval

时间:2018-11-19 01:38:30

标签: reactjs

由于某种原因,此处的条件(“ if id === reset”)不起作用:既未清除间隔,也未重置状态。如果我在setInterval中移动“ const id”,则会得到“ undefined”,这可能是因为它的值。不幸的是,我不知道如何解决它。

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

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

handleSession(event){
const id= event.target.id;
let breakvar= this.state.break;
let sessionvar= this.state.session;
let isRunning=this.state.isRunning;

if(!isRunning && id==="break-increment" && breakvar<=59){
this.setState((state) => ({
  break: this.state.break +1}))}
}

else if (!isRunning && id==="session-decrement" && sessionvar>1){
this.setState((state) => ({
  session: this.state.session -1, timer:this.state.timer - 60}))}   
}   
 handleTimer(evt){
      const id=evt.target.id;
      clearInterval(this.Interval)
      this.Interval=setInterval(() => { 
        let timer=this.state.timer;
        if(timer > 0){
          this.setState({
            timer: this.state.timer - 1
          })
        }else if(id==="reset"){
     clearInterval(this.Interval);
     this.setState((state) => ({
      session: 25, timer:1500, break:5, isRunning:false}))
        }
        else{
          clearInterval(this.Interval)}
      },1000)}

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.handleSession} id="break-increment"/>
                <p id="session-label">Session length</p>
                <Button onClick={this.handleSession} id="session-decrement"/>
                <Button onClick={this.handleTimer} id="start_stop"/>
                <Button onClick={this.handleTimer} id="reset"/>
            </div>
)

}

2 个答案:

答案 0 :(得分:1)

您的else语句将永远不会到达,因为timer几乎总是大于0,除非定时器用完了。因此,当用户按下reset键时,if( timer > 0 )的情况将会发生,并且永远不会进入else if(id==="reset")

这是您的代码,请注意,我将break重命名为break1,因为break是JavaScript中的保留字。

handleSession(event){
  const id = event.target.id;
  const { break1, session, isRunning } = this.state;

  if(!isRunning && id==="break-increment" && break1<=59) {
    this.setState({
      break1: this.state.break1 +1
    })
  } else if (!isRunning && id==="session-decrement" && session > 1) {
    this.setState((state) => ({
      session: this.state.session -1, timer:this.state.timer - 60
    }))
  }   
}

handleTimer(evt) {
  const id=evt.target.id;
  clearInterval(this.Interval)

  this.Interval=setInterval(() => { 
    let timer=this.state.timer;
    if(timer > 0 && id !== 'reset'){
      this.setState({
        timer: this.state.timer - 1
      })
    } else if (id==="reset") {
      clearInterval(this.Interval);
      this.setState({
        session: 25, timer:1500, break1:5, isRunning:false
      })
    } else {
      clearInterval(this.Interval);
    }
  }, 1000)
}

演示

https://repl.it/@AnonymousSB/SO53367240

注意:没有实际的DisplayButton组件,我不得不替换渲染。

答案 1 :(得分:0)

这是带有ES6箭头功能的工作示例:

import React, { Component, Fragment } from "react";

export default class MyComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {};
  }

  handleTimer = id => {
    clearInterval(this.interval);
    this.interval = setInterval(() => {
      let timer = this.state.timer;
      if (timer > 0) {
        this.setState({
          timer: this.state.timer - 1
        });
      } 
    }, 1000);
        else if (id === "reset") {
        clearInterval(this.interval);
        this.setState(state => ({
          session: 25,
          timer: 1500,
          break: 5,
          isRunning: false
        }));
      }
  };

  render() {
    return (
      <Fragment>
        <button onClick={() => this.handleTimer('reset')}>Reset</button>
        <button onClick={() => this.handleTimer('start')}>Start</button>
      </Fragment>
    );
  }
}

请注意,我已经使用了ES6箭头功能,因此可以通过单击按钮上的 this 来使用它。如果您喜欢坚持自己的实现,请确保在构造函数中绑定到此:

 export default class MyComponent extends Component {
      constructor(props) {
        super(props);
        this.handleTimer = this.handleTimer.bind(this);
      }

这是一个有效的代码框:https://codesandbox.io/s/wq253893w5