dark09aura
dark09aura

Reputation: 63

React Timer using seState and Interval not Working

I have a timer MM:SS that is counting upwards to a set time of MM:SS. i.e. from 00:00 to 45:00.

My state is current set at.

  const [currentTime, setCurrentTime] = useState<CurrentTime>({
    minutes: 0,
    seconds: 58,
  });

My useEffect timer to continiously update time is set up as...

 useEffect(() => {
  let interval: any;

  if (!finished) {
  interval = setInterval(() => {
    if (currentTime.seconds === 60) {
      setCurrentTime({
        ...currentTime,
        minutes: currentTime.minutes++,
        seconds: 0,
      });
    } else {
      setCurrentTime({
        ...currentTime,
        minutes: currentTime.minutes,
        seconds: currentTime.seconds++,
      });
    }

   }, 1000);
    } else {
      clearInterval(interval);
    }

    return () => clearInterval(interval);
  }, [finished]);

The problem I have is that when the seconds reach 60. The minute property updates, but the seconds property never updates and is always stuck at 60, leading to a continuous output of 01:00, 02:00, 03:00, 04:00 05:00, ..., in the console.

What do I need to do so that when 60 seconds is reached, the minute goes up by 1 and the seconds goes back to 0 at the same time.

Upvotes: 4

Views: 504

Answers (1)

Drew Reese
Drew Reese

Reputation: 202751

Looks like you are mutating state and have an issue with stale enclosure. Use a functional state update to correctly update from the previous state. Move the conditional check on currentTime.seconds into the functional update. You will also want to check and "reset" the seconds to 0 when 59 seconds is reached so that on the next "tick" it is 0 instead of reaching 60.

useEffect(() => {
  let interval;

  if (!finished) {
    interval = setInterval(() => {
      setCurrentTime((currentTime) => {
        if (currentTime.seconds === 59) {
          return {
            ...currentTime,
            minutes: currentTime.minutes + 1,
            seconds: 0
          };
        } else {
          return {
            ...currentTime,
            minutes: currentTime.minutes,
            seconds: currentTime.seconds + 1
          };
        }
      });
    }, 1000);
  } else {
    clearInterval(interval);
  }

  return () => clearInterval(interval);
}, [finished]);

Edit react-timer-using-sestate-and-interval-not-working

Upvotes: 2

Related Questions