I need to call ClearInterval from a different function

Viewed 242

I'm creating a countdown timer and I need to call clearInterval from a different function as I want to start and pause the countdown with two different buttons

Here's a piece of my code

const startCountdown = () => {
    const countdown = setInterval(() => {
      setSecondsElapsed(secondsElapsed => secondsElapsed - 1);
    }, 1000);
  };

  const pauseCountdown = () => {
    clearInterval(countdown);
  };

The countdown starts when I press the initial button but it doesn't pause when I press the button calling pauseCountdown()

3 Answers

Use a React ref to hold the timer reference. When setting the interval store the countdown reference as the ref's current value, and in the other function clear the interval using the ref's current value.

const countDownRef = React.useRef();

const startCountdown = () => {
  countDownRef.current = setInterval(() => {
    setSecondsElapsed(secondsElapsed => secondsElapsed - 1);
  }, 1000);
};

const pauseCountdown = () => {
  clearInterval(countDownRef.current);
};

try declaring countdown globally so it can be accessed from any function. I'd also recommend using var instead of const for things that will be frequently redefined, such as a pausable countdown loop.

try this:

var countdown;

const startCountdown = () => {
    countdown = setInterval(() => {
      setSecondsElapsed(secondsElapsed => secondsElapsed - 1);
    }, 1000);
  };

  const pauseCountdown = () => {
    clearInterval(countdown);
  };

The countdown value is inside the scope of startCountdown function hence it can not be accessed from pauseCountdown function which is not inside that very scope.

There are many different ways to do this job properly. I would advise you to be more structural with the help of new abstractions.

I may perhaps use a Countdown class for this job.

class Countdown {
  #sid;
  #start;
  constructor(start){
    this.#start = start;
  }
  startCountdown(){
    this.#sid = setInterval( _ => ( !this.#start && clearInterval(this.#sid)
                                  , console.log(this.#start--)
                                  )
                           , 1000
                           );
  }
  pauseCountdown(){
    clearInterval(this.#sid);
  }
}

var cd = new Countdown(10);
cd.startCountdown();
setTimeout(_ => cd.pauseCountdown(), 5001)
setTimeout(_ => cd.startCountdown(), 10000)

The private class fields #sid and #start keep the clearInterval id and starting value respectively. The thing is they are not exposed to the outer world.

Related