user1189352
user1189352

Reputation: 3885

Stopping a timer in useEffect

From what I can tell, the timer being called in a different scope.. how can I accomplish a function to stop the timer? Going a bit crazy here, thank you for any help.

const SomeComponent = ({ isPlaying }) => {
  let timer = null;

  React.useEffect(() => {
    if (isPlaying) {
      startTimer();
    }
  },[isPlaying]);

  const startTimer = () => {
    timer = setInterval(() => {
      console.log('tick');
    }, 1000);
  };

  const stopTimer = () => {
    console.log('stopping timer: ', timer);  // shows null, instead of giving the timerId to stop properly
    clearInterval(timer);
  };

Upvotes: 2

Views: 2066

Answers (1)

Chris
Chris

Reputation: 59531

The timer variable will "reset" each time your component is re-rendered. Even if it holds your timer, a re-render will set its value to null again.

You could either move out of the component scope, or use useRef to keep the variable through re-renders:

const SomeComponent = ({ isPlaying }) => {
  const timer = React.useRef(null);

  React.useEffect(() => {
    if (isPlaying) {
      startTimer();
    }

    return () => clearInterval(timer.current);
  }, [isPlaying]);

  const startTimer = () => {
    timer.current = setInterval(() => {
      console.log('tick');
    }, 1000);
  };

  const stopTimer = () => {
    clearInterval(timer.current);
  };

Note that I also force a clearInterval by using a return inside the useEffect. This way the component will automatically "clean up" when it unmounts. I also changed timer to be a constant.

Upvotes: 1

Related Questions