6

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>
 })
}
Francesco Clementi
  • 1,874
  • 4
  • 13
  • 28

1 Answers1

15

My 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>
 })
}
Francesco Clementi
  • 1,874
  • 4
  • 13
  • 28