Why a simple useEffect
is not taking updated value when it is warping any setInterval/timeout inside;
where variable stopped to initial value;
import { useState, useEffect } from "react";
let timerRef;
const StopWatch = () => {
const [time, setTime] = useState(0);
const [isPause, setPause] = useState(false);
useEffect(() => {
timerRef = setInterval(() => {
console.log({ time });
if (!isPause) {
setTime(time + 1);
}
}, 5000);
return () => clearInterval(timerRef);
}, []);
const startWatch = () => {
setPause(false);
};
const stopWatch = () => {
setPause(true);
};
return (
<>
time: {time}
<button onClick={startWatch}>Start</button>
<button onClick={stopWatch}>stop</button>
</>
);
};
export { StopWatch };
That is because you are accessing time
value from the closure, and since you are defining setTimeout handler only once (on initialization) then it will always refer to that initial value for time
. I suggest, for this use case, just to use state updater with callback, and like that it will provide you mechanism to easily update state with previos one, and by not accessing state directly. Just rewrite setTime(_time + 1)
to setTime(prevTime => prevTime + 1)