Search code examples
javascriptreactjstypescripttimer

React If Timer expired


I'm currently trying to make an API call when my timer hits zero OR is in the past.

This is my Timer componenet

import { useState, useEffect } from "react";
import Box from "@mui/material/Box";
import { useDispatch } from "react-redux";
import { AppDispatch } from "../store";

const Timer = ({ deadline }: { deadline: Date }) => {
  const [timeRemaining, setTimeRemaining] = useState(getTimeRemaining(deadline));
  const [timerExpired, setTimerExpired] = useState(false);

  useEffect(() => {
    const intervalId = setInterval(() => {
      const remaining = getTimeRemaining(deadline);
      setTimeRemaining(remaining);

      if(remaining.days <= 0 && remaining.hours <= 0 && remaining.minutes <= 0 && remaining.seconds <= 0) {
        setTimerExpired(true);
        clearInterval(intervalId);

        const dispatch = useDispatch<AppDispatch>();
        try{
          console.log("TIMER EXPIRED");
        } catch (e){
          /* redux handles error */
        }
      }
    }, 1000);

    return () => clearInterval(intervalId);
  }, [deadline]);

  const { days, hours, minutes, seconds } = timeRemaining;

  return (
    <Box
    sx={{
      display: "flex",
      flexDirection: "column",
      alignItems: "center",
      justifyContent: "center",
      padding: "20px",
      fontSize: "35px",
      fontWeight: "bold"
    }}
  >
    {timerExpired ? (
      <p>Timer has expired.</p>
    ) : (
      <>
        {days === 1 ? (
          <p>
            {days} day {hours} hours {minutes} minutes {seconds} seconds
          </p>
        ) : (
          <p>
            {days} days {hours} hours {minutes} minutes {seconds} seconds
          </p>
        )}
      </>
    )}
  </Box>
      );
}

const getTimeRemaining = (deadline: Date) => {
  const total = deadline.getTime() - new Date().getTime();
  const days = Math.floor(total / (1000 * 60 * 60 * 24));
  const hours = Math.floor((total / (1000 * 60 * 60)) % 24);
  const minutes = Math.floor((total / 1000 / 60) % 60);
  const seconds = Math.floor((total / 1000) % 60);

  return {
    days,
    hours,
    minutes,
    seconds
  };
};

export default Timer;

In this component i initialize the timer with the time it should expire:

const creationDate = new Date("2023-07-12");
    creationDate.setHours(9);
    creationDate.setMinutes(0);
    creationDate.setSeconds(0);

<Timer deadline={creationDate}/>

the console.log("TIMER EXPIRED") is never called, even when i set the createionDate to 2023-01-01 or any day in the past.

If you need any more information, please do not hesitate to comment.

Thanks in advance.


Solution

  • You could add total to the return in getTimeRemaining, and then check that.

    if ( remaining.total <= 0 ) {
    

    Then your code should work I have made an example stackblitz.