useEffect with setInterval to make a timer.

If you are using setInterval with useEffect, you may have got some weird bugs on the run. If you wanted to make a timer, you would create it like this at first,

const [time,setTime] = useState(60);
useEffect(()=>{
   setInterval(()=>{
     setTime(time => time-1);
   },1000);
},[time]);

Here, you forgot that as time changes, useeffect re-run or re-renders the setInterval which re-applies it from where it left in the old memory, hence we need to do something which clears out the old setInterval.

Here, you can observe the time will output like this and returns the time value like this in the console: 60,59,57,47,... This is because it re-runs from its initial result of time to the last updated one and if the time is 1000ms, then we will never see the newly updated time while it looks like you've given 1ms in setInterval.

To clear out the old setInterval value in the memory you've to use clearInterval(), setInterval() returns a unique id to clear the setInterval.

the code will look like this:

const [time,setTime] = useState(60);

useEffect(()=>{
   let id = setInterval(()=>{
             setTime(time => time-1);
        },1000);

    return ()=>{
                clearInterval(id);
    }
},[time]);

Now it clears out the old setInterval from the memory, on each re-render because of the dependency array '[time]' which freshly runs and applies changes to time.

Wanted to stop the time on 0

If you wanted to stop the time on 0, then you have to clear out the setInterval when the time occurs at 0, Here's the code:

const [time,setTime] = useState(60);

useEffect(()=>{
   let id = setInterval(()=>{
             setTime(time => time-1);
        },1000);

    if(time === 0){
        clearInterval(id);
    }

    return ()=>{
                clearInterval(id);
    }
},[time]);

You may now be confused about how it will stop the useEffect from re-rendering and stop time to 0. This is because each executable line is asynchronously executing in the memory and, as the time is 0 already, it clears out the setInterval with the unique id and stops it. Hence, it didn't change the time and useEffect will not run after it.

0
Subscribe to my newsletter

Read articles from Tushar Mukherjee directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Tushar Mukherjee
Tushar Mukherjee