I'm trying to implement a 5 seconds countdown using hooks in react. On others answers, the solution is to implement setInterval with React.useEffect, but I'd like to let the final user to trigger the countdown with a button. Then, at the end of the coundown, execute a function.
I managed the show the timer, but I didn't manage to execute a function when the timer is 0. In the following case, the console.log is not triggered.
function Test(){
const [timeLeft, setTimeLeft] = useState(null);
useEffect(() => {
// exit early when we reach 0
if (!timeLeft) return;
if(timeLeft===0){
console.log("TIME LEFT IS 0");
setTimeLeft(null)
}
// save intervalId to clear the interval when the
// component re-renders
const intervalId = setInterval(() => {
setTimeLeft(timeLeft - 1);
}, 1000);
// clear interval on re-render to avoid memory leaks
return () => clearInterval(intervalId);
// add timeLeft as a dependency to re-rerun the effect
// when we update it
}, [timeLeft]);
return (
<React.Fragment>
{timeLeft}
<Button onClick={()=>setTimeLeft(5)} className={classes.button}>
TEST
</Button>
</React.Fragment>
})
}
I'm trying to implement a 5 seconds countdown using hooks in react. On others answers, the solution is to implement setInterval with React.useEffect, but I'd like to let the final user to trigger the countdown with a button. Then, at the end of the coundown, execute a function.
I managed the show the timer, but I didn't manage to execute a function when the timer is 0. In the following case, the console.log is not triggered.
function Test(){
const [timeLeft, setTimeLeft] = useState(null);
useEffect(() => {
// exit early when we reach 0
if (!timeLeft) return;
if(timeLeft===0){
console.log("TIME LEFT IS 0");
setTimeLeft(null)
}
// save intervalId to clear the interval when the
// component re-renders
const intervalId = setInterval(() => {
setTimeLeft(timeLeft - 1);
}, 1000);
// clear interval on re-render to avoid memory leaks
return () => clearInterval(intervalId);
// add timeLeft as a dependency to re-rerun the effect
// when we update it
}, [timeLeft]);
return (
<React.Fragment>
{timeLeft}
<Button onClick={()=>setTimeLeft(5)} className={classes.button}>
TEST
</Button>
</React.Fragment>
})
}
Share
Improve this question
edited Dec 4, 2019 at 15:00
Francesco Clementi
asked Dec 4, 2019 at 14:44
Francesco ClementiFrancesco Clementi
2,1024 gold badges15 silver badges31 bronze badges
2
- 1 Show us what you tried. – trixn Commented Dec 4, 2019 at 14:47
- @trixn Edited the question – Francesco Clementi Commented Dec 4, 2019 at 15:00
1 Answer
Reset to default 18My mistake. The 0 will trigger the return in the useEffect. I had just to move the check above it:
function Test(){
const [timeLeft, setTimeLeft] = useState(null);
useEffect(() => {
if(timeLeft===0){
console.log("TIME LEFT IS 0");
setTimeLeft(null)
}
// exit early when we reach 0
if (!timeLeft) return;
// save intervalId to clear the interval when the
// component re-renders
const intervalId = setInterval(() => {
setTimeLeft(timeLeft - 1);
}, 1000);
// clear interval on re-render to avoid memory leaks
return () => clearInterval(intervalId);
// add timeLeft as a dependency to re-rerun the effect
// when we update it
}, [timeLeft]);
return (
<React.Fragment>
{timeLeft}
<Button onClick={()=>setTimeLeft(5)} className={classes.button}>
TEST
</Button>
</React.Fragment>
})
}