如何阻止第二个React计时器从零循环回来?

时间:2017-07-22 23:44:18

标签: javascript reactjs

我正在尝试构建一个具有两个定时器的React组件。第一个是三秒钟,当它达到零时,它表示" GO!"然后立即开始下一个,这是一个60秒的计时器。我已经完成了所有这些工作,但我无法弄清楚如何阻止60秒计时器在它达到零时重新开始。理想情况下,一旦我弄明白,我将把它们分成两个组件,但是现在我只想让一切正常工作。有人能引导我朝着正确的方向前进吗?

import React, { Component } from "react";
import ReactDOM from "react-dom"

class Countdown extends React.Component {
  constructor(props) {
    super(props);

    this.state = { time: {}, seconds: 3 };
    this.timer = 0;
    this.startTimer = this.startTimer.bind(this);
    this.countdown = this.countdown.bind(this);
  }

  formatSeconds (totalSeconds) {
    let seconds = totalSeconds;
    let minutes = Math.floor(totalSeconds / 60);

    if (seconds < 10) {
      seconds = '0' + seconds;
    }

    if (minutes < 10) {
      minutes = '0' + minutes;
    }

    let obj = {
      "minutes": minutes,
      "seconds": seconds
    };

    return obj;
  }

  componentDidMount() {
    let timeLeft = this.formatSeconds(this.state.seconds);
    this.setState({ time: timeLeft });
  }

  startTimer() {
    if (this.timer === 0) {
      this.timer = setInterval(this.countdown, 1000);
    }
  }

  countdown() {
    let seconds = this.state.seconds - 1;
    this.setState({
      time: this.formatSeconds(seconds),
      seconds: seconds
    });

    if (seconds === 0) {
      clearInterval(this.timer);

        let element = (
          <h2>GO!</h2>
        );
        ReactDOM.render(
          element,
          document.getElementById('go')
        );

      this.state.seconds = 61;
      let seconds = this.state.seconds - 1;
      this.timer = setInterval(this.countdown, 1000);
      this.setState({
        time: this.formatSeconds(seconds),
        seconds: seconds
      });
      // how do I stop the second timer from looping?
    }
  }


  render() {
    return(
      <div className="container">
        <div className="row">
          <div className="column small-centered medium-6 large-4">
            <h2 id="go"></h2>
            {this.state.time.seconds}<br />
            <button className="button" onClick={this.startTimer}>Start</button>
          </div>
        </div>
      </div>
    );
  }
}

export default Countdown;

1 个答案:

答案 0 :(得分:1)

你可以把它分成两个倒计时功能,如下所示吗?

class Countdown extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            countdownSeconds: 3,
            roundSeconds: 60
        };

        this.countdown = this.countdown.bind(this);
        this.roundCountdown = this.roundCountdown.bind(this);
        this.startTimer = this.startTimer.bind(this);
    }

    startTimer() {
        if(!this.countdownTimer) {
            this.countdownTimer = setInterval(this.countdown, 1000);
        }
    }

    countdown() {
        const currentSeconds = this.state.countdownSeconds - 1;

        this.setState({
            countdownSeconds: currentSeconds
        });

        if(currentSeconds === 0) {
            this.roundTimer = setInterval(this.roundCountdown, 1000);
            clearInterval(this.countdownTimer);
        }
    }

    roundCountdown() {
        const currentSeconds = this.state.roundSeconds - 1;

        this.setState({
            roundSeconds: currentSeconds
        });

        if(currentSeconds === 0) {
            //do whatever
            clearInterval(this.roundTimer);
        }
    }
}

修改

如果我理解您的其他问题,要显示适当的倒计时,您可以执行类似

的操作
render() {
    const { countdownSeconds, roundSeconds } = this.state;

    return (
        <div>
        {countdownSeconds > 0 &&
            <span>Counting down...{countdownSeconds}</span>
        }
        {roundSeconds > 0 && countdownSeconds === 0 &&
            <span>Round underway...{roundSeconds}</span>
        }
        </div>
    );
}

或者你可以使计时器的渲染功能化,即

renderTimer() {
    const { countdownSeconds, roundSeconds } = this.state;

    if(countdownSeconds > 0) {
        return <span>Counting down...{countdownSeconds}</span>;
    }

    return <span>Round underway...{roundSeconds}</span>;
}

然后:

render() {
    return (
        <div>
            {this.renderTimer()}
        </div>
    );
}