Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

158
Views
Best way to use setInterval inside React useEffect in countdown timer

newbie to Javascript & React, trying to learn my way through React by building small projects. I'm working on a countdown timer right now, and I'm wondering if there's a better way of handling the pause/stop logic.

Right now, I'm calling setInterval() when my component is no longer in a "Paused" !paused state, and returning a cleanup() function to clear the interval. When I console logged it, it only cleared interval on pause/start.

However, I want to add functionality to automatically stop the timer once it hits zero, which requires adding duration state as a second dependency. When I logged this to console, I realized that my setDuration and clearInterval was now running at every interval, rather than only on the pause/start (it looks like it's calling setInterval() at every "tick" now.

My question is - is this a problem? And is there a better way to do this?

function Timer(props) {
  const [duration, setDuration] = useState(10);
  const [paused, setPaused] = useState(true);

  useEffect(() => {
    let timerId;
    if (!paused) {
      timerId = setInterval(() => {
        setDuration(prev => prev - 1);
      }, 1000);
      // console.log(timerId);
    }

    if (duration === 0) {
      // console.log(`Time's up`);
      clearInterval(timerId);
    }

    return function cleanup() {
      // console.log(`Clearing ${timerId}`);
      clearInterval(timerId);
    };
  }, [paused, duration]);

  const handleClick = (e) => {
    !paused ? setPaused(true) : setPaused(false);
  };

  return (
    <>
      <h3>{duration}</h3>
      <Button paused={paused} onClick={handleClick} />
    </>
  );
}
about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

In your code, duration is changing on every interval and because it is passed as a parameter in dependecy array, it is triggering useEffect on each interval which is causing it to the setDuration and clearInterval to run at each interval.

you can use ternary operator to check if the duration is less than zero then you can automatically set the duration to zero by using setDuration(0)

function Timer(props) {
      const [duration, setDuration] = useState(10);
      const [paused, setPaused] = useState(true);
    
      useEffect(() => {
        let timerId;
        if (!paused) {
          timerId = setInterval(() => {
            setDuration((prev) => prev - 1);
          }, 1000);
          console.log(timerId);
        }
    
        return function cleanup() {
          console.log(`Clearing ${timerId}`);
          clearInterval(timerId);
        };
      }, [paused]);
    
      const handleClick = (e) => {
        !paused ? setPaused(true) : setPaused(false);
      };
    
      return (
        <>
          {duration >= 0 ? <h3>{duration}</h3> : setDuration(0)}
          <button paused={paused} onClick={handleClick} />
        </>
      );
    }

Play around with the code here

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!