1

I'm using Reactjs to make a countdown timer that can separate to day, hours, minutes, and seconds between 2 dates. It works fine, but It can only count to a date that is larger than the current date (21/08/2022 < 17/10/2022), but It cannot count to (21/08/2022 to 21/08/2023). I have a function to pass down props:

const timeLeft = useCountdown(new Date(2022, Data.date.month , Data.date.day));  

It should look like this when console.log:

{days: 87, hours: 20, minutes: 58, seconds: 40}

I'm using a useCountDown hook to count the time between 2 dates:

import { useState, useEffect } from "react";

const useCountdown = (deadline) => {
    const [days, setDays] = useState(0);
    const [hours, setHours] = useState(0);
    const [minutes, setMinutes] = useState(0);
    const [seconds, setSeconds] = useState(0);
  
    const leading0 = (num) => {
      return num < 10 ? "0" + num : num;
    };
  
    const getTimeUntil = (deadline) => {
      const time = Date.parse(deadline) - Date.parse(new Date());
      if (time < 0) {
        setDays(0);
        setHours(0);
        setMinutes(0);
        setSeconds(0);
      } else {
        setDays(Math.floor(time / (1000 * 60 * 60 * 24)));
        setHours(Math.floor((time / (1000 * 60 * 60)) % 24));
        setMinutes(Math.floor((time / 1000 / 60) % 60));
        setSeconds(Math.floor((time / 1000) % 60));
      }
    };
  
    useEffect(() => {
      setInterval(() => getTimeUntil(deadline), 1000);
  
      return () => getTimeUntil(deadline);
    }, [deadline]);
    
    return {
        days: leading0(days),
        hours: leading0(hours),
        minutes: leading0(minutes),
        seconds: leading0(seconds)
    };
};

export default useCountdown;

I haven't figured out how to fix this. Sorry for the bad English, but I'm trying my best :( Thank you for helping me!

1 Answer 1

3

Here's a much simpler version:

const useCountdown = (deadline: Date) => {
  // Time is in seconds
  const [time, setTime] = useState(
    Math.max(0, Math.floor((deadline.getTime() - Date.now()) / 1000))
  );

  const decrement = () =>
    setTime((prevTime) => {
      return prevTime === 0 ? 0 : prevTime - 1;
    });

  useEffect(() => {
    const id = setInterval(decrement, 1000);
    return () => clearInterval(id);
  }, []);

  const format = (num: number): string => {
    return num < 10 ? '0' + num : num.toString();
  };

  return {
    days: format(Math.floor(time / (3600 * 24))),
    hours: format(Math.floor((time / 3600) % 24)),
    minutes: format(Math.floor((time / 60) % 60)),
    seconds: format(time % 60),
  };
};

Stackblitz: https://stackblitz.com/edit/react-ts-bnhvxp?file=App.tsx

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.