Search code examples
javascriptreactjsreact-hookscountdown

React - 5 seconds countdown with hooks


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>
 })
}

Solution

  • 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>
     })
    }