I was trying to create a stopwatch, when I run it, it's counting the seconds in even numbers like 0 - 2 - 4 - 6....... I don't understand why.
I don't find any error in the code. if anyone can help, it would be helpful
export default function Stopwatch() {
let [ispaused,setIspaused ] = useState(false);
let [seconds, setSeconds] = useState (0);
let secondsref = useRef(seconds)
let ispausedRef = useRef(ispaused);
let watch = useRef(0);
let initTicker= ()=>{
ispausedRef.current = true
setIspaused(true);
}
let stopTicker=()=>{
ispausedRef.current = false
setIspaused(false)
//setSecondsleft(secondsleftRef.current);
}
let resethndler = ()=>{
setIspaused(false)
ispausedRef.current = false;
secondsref.current=0;
setSeconds(0);
}
let Tick = ()=>{
secondsref.current =1;
setSeconds(secondsref.current);
}
useEffect(()=>{
watch.current = setInterval(()=>{
if (!ispausedRef.current){
return;
}
Tick();
},1000)
},[])
let percantage = ((seconds`)/60)*100
return (
<div>
<div className='stopwatch'>
<CircularProgressbar
ssbar value={percantage} text={`0${parseInt(seconds/60)}`.slice(-2) ":" `0${seconds`}`.slice(-2)} />
</div>
}
CodePudding user response:
Fasten your seat belt it will be fun! :)
I assume you're using <StrictMode>
. This mode will mount / unmount / remount your components to identify potential issues in lifecycle. Only on development environment. You can read more about it from React documentation.
So once that is said, your component is in fact mounted twice so you're creating 2 intervals. And as React batches setState
, it seems to count numbers 2 by 2. But it's in fact 2 different intervals.
So solution here is in your useEffect
, which must return a cleanup function, which will destroy your interval
useEffect(() => {
...
return () => clearInterval(watch.current)
}, [])
CodePudding user response:
As @dbuchet said, it may be because of <StrictMode>
.
I've made a (bit simplified) version in codesandbox. Notice the commented out StrictMode
in index.js
. The counter works correct.