Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

clearInterval not stopping my counter in useEffect

I'm trying to use a setInterval and a clearInterval within useEffect React hook. The timer starts as expected, but it won't stop. I am assigning setInterval to intervalID then calling clearInterval(intervalID)

  useEffect(() => {
    console.log(`isRunning changed to: ${state.isRunning}`); //isRunning changed to: start
    let intervalID;
    console.log(`initial interval is: ${intervalID}`); // initial interval is: undefined
    if (state.isRunning === "start") {
      intervalID = setInterval(() => {
        console.log(`interval is: ${intervalID}`); // interval is: 7
        console.log(`tic toc`);
        dispatch({ type: "tic-toc" });
      }, 1000);
    } else if (state.isRunning === "stop") {
      console.log("clearInterval stop!"); // when I set isRunning to stop, this log shows in the console, but the next line doesn't stop the timer.
      clearInterval(intervalID);
    }
  }, [state.isRunning]);

full code: https://github.com/LazaroFilm/pomodoro

like image 318
Victor Lazaro Avatar asked Oct 17 '20 19:10

Victor Lazaro


People also ask

How do you stop an interval in useEffect?

A function or block of code that is bound to an interval executes until it is stopped. To stop an interval, you can use the clearInterval() method. ... useEffect(() => { const interval = setInterval(() => { setSeconds(seconds => seconds + 1); }, 1000); return () => clearInterval(interval); }, []); ...

Does clearInterval stop?

I did make a fiddle to test it, and it turns out clearInterval stops all future execution, even those that have already be queued.

How do you stop setInterval counter?

Answer: Use the clearInterval() Method The setInterval() method returns an interval ID which uniquely identifies the interval. You can pass this interval ID to the global clearInterval() method to cancel or stop setInterval() call.

Can you clearInterval within setInterval?

Calling clearInterval() inside setInterval() has no effect But after calling clearInterval(), it will continue to execute.

How to clear The setInterval() timer in Java?

Therefore, you can simply clear the setInterval () timer in this clean-up function, for example in the following way: // ... useEffect( () => { const timerId = setInterval( () => { // do something }, 2000); return () => clearInterval(timerId); }, []); // ...

Does clearinterval (rungame) work?

I watch the condition execute clearInterval (rungame) This should freeze the game before the snake can move outside the canvas. But it doesn’t? Even though I watch the condition execute the clear interval? The clearInterval is working. When an out of bounds condition occurs, the game function doesn’t get called again.

Why does my useeffect render in infinite mode?

Because this useEffect will trigger whenever there is change in either count or timer. In your case you are changing timer in useEffect itself which is causing infinite rendering. So, remove timer from dependency array (or remove setTimer function in case you don't need it) and try!

Why does useeffect trigger when settimer is set?

You are adding setTimer in return and at the same time you are adding timer variable in dependency array which will cause infinite rendering. Because this useEffect will trigger whenever there is change in either count or timer.


1 Answers

I think you neither need to use useState nor useRef hooks for the intervalID. Declare it outside the useEffect but clear the interval in the cleanup function of the useEffect hook like so

let intervalID;
useEffect(() => {
    if (isRunning) {
      intervalID = setInterval(() => {
        dispatch({ type: "tic-toc" });
      }, 1000);
    }
      return () => clearInterval(intervalID);
  }, [isRunning]);

Whenever isRunning changes the component will unmount, and the cleanup function will be executed. So, if the isRunning has changed to false then the timer should stop at the unmount, and when it's mounted again the condition in the if statement won't be met to run the setInterval, and thus the timer remains stopped. In my code I assumed isRunning is boolean (which is the way I prefer it to be), and assumed it's "destructured" from the state which I assume comes from useReducer hook.

like image 140
BlackMath Avatar answered Oct 16 '22 21:10

BlackMath