Reputation: 1222
I have a stopwatch function in React that I would like to stop after 15 minutes. I am not sure how to use clearInterval()
in this case:
const [timer, setTimer] = useState(0);
const [isActive, setIsActive] = useState(false);
const [isPaused, setIsPaused] = useState(false);
const countRef = useRef(null);
const lastUpdatedRef = useRef(null);
const [minutes,setMinutes] = useState(0)
const [seconds,setSeconds] = useState(0)
const timeCeiling = 900; //maximum minutes is 15
const timeFloor = 60; //maximum seconds is 60 so it resets after
useEffect(() => {
if (timer < timeCeiling) {
setMinutes(Math.floor(timer / 60));
setSeconds(timer % 60);
} else {
setMinutes(15);
setSeconds(0);
}
}, [timer]);
const handleStart = () => {
setIsActive(true);
setIsPaused(true);
countRef.current = setInterval(() => {
setTimer((timer) => timer + 1);
}, 1000);
lastUpdatedRef.current = setInterval(() => {
setLastUpdated(Date.now());
}, 30000);
};
The user clicks on the handleStart
function which triggers a useEffect
. It also has a lastUpdated
dependency which triggers another function every 30 seconds.
The clock should end after 15:00 but it still continues after- where should I put clearInterval
so that it stops the clock after 15 minutes? Or is there another way to do this?
Upvotes: 3
Views: 1146
Reputation: 12787
You can add cleare interval in the else condition:
useEffect(() => {
if (timer < timeCeiling) {
setMinutes(Math.floor(timer / 60));
setSeconds(timer % 60);
} else {
setMinutes(15);
setSeconds(0);
countRef.current && clearInterval(countRef.current);
lastUpdatedRef.current && clearInterval(lastUpdatedRef.current);
}
}, [timer]);
And you should cleare interval when component un-mount:
useEffect(() => {
return () => {
countRef.current && clearInterval(countRef.current);
};
}, [countRef]);
useEffect(() => {
return () => {
lastUpdatedRef.current && clearInterval(lastUpdatedRef.current);
};
}, [lastUpdatedRef]);
Upvotes: 1
Reputation: 900
I think you should use clearInterval
in the else block in useEffect
. Maybe this way:
else {
setMinutes(15);
setSeconds(0);
clearInterval(countRef.current) // I hope this works
}
Upvotes: 1
Reputation: 202706
I would place it in the useEffect
that is running each time timer
updates. Clear the interval in the else branch when the limit it hit.
useEffect(() => {
if (timer < timeCeiling) {
setMinutes(Math.floor(timer / 60));
setSeconds(timer % 60);
} else {
clearInterval(countRef.current);
setMinutes(15);
setSeconds(0);
}
}, [timer]);
You might also want to add an additional useEffect
hook to clear any running timers should the component unmount before you manually clear them.
useEffect(() => {
return () => {
clearInterval(countRef.current);
clearInterval(lastUpdatedRef.current);
};
}, []);
Upvotes: 2