wildlifehexagon
wildlifehexagon

Reputation: 523

How to stop a second React timer from looping back from zero?

I'm trying to build a React component that has two timers. The first one is three seconds, and when it hits zero it says "GO!" then immediately starts the next one, which is a 60 second timer. I got all of this to work, but I can't figure out how to stop the 60 second timer from starting over when it hits zero. Ideally I will be splitting these into two components once I figure this out, but right now I just want to get everything to work properly. Can someone steer me in the right direction here?

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;

Upvotes: 0

Views: 2090

Answers (1)

Anthony
Anthony

Reputation: 6482

Could you break it out into two countdown functions as follows?

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);
        }
    }
}

Edit:

If I understand your other question, to display the appropriate countdown you could maybe do something like

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>
    );
}

Or you could functionalize the rendering of the the timer, i.e.

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

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

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

and then:

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

Upvotes: 1

Related Questions