尝试使用 UseEffect 在 react.js(天:小时:分钟:秒)中创建倒计时

Trying to create a Countdown in react.js (day : hours : minutes : seconds) with UseEffect

正如标题所说,我正在尝试创建一个从

开始的倒计时

4 days : 23 hours : 59 minutes : 59 seconds ,倒数到 0 days: 0 hours : 0 minutes : 0 seconds

到目前为止我有以下内容

import * as React from "react";

const Countdown = (props) => {
  const [seconds, setSeconds] = React.useState(2);
  const [minutes, setMinutes] = React.useState(2);
  const [hours, setHours] = React.useState(2);
  const [days, setDays] = React.useState(4);
  const [timeDone, setDone] = React.useState(false);
 //SECONDS

  //seconds 60 -> 0
  React.useEffect(() => {
    const secondsCounter =
      seconds > 0 && setInterval(() => setSeconds(seconds - 1), 1000);
    return () => clearInterval(secondsCounter);
  }, [seconds]);

  //seconds == 60 (when seconds == 0)
  React.useEffect(() => {
    return () => setSeconds(2);
  }, [seconds == 0 && !timeDone ]);

//MINUTES

  //Minutes 60 -> 0  (when seconds == 0)
  React.useEffect(() => {
    return () => setMinutes(minutes-1)
  }, [seconds == 0]);

  //Minutes == 60 (when minutes == 0)
  React.useEffect(() => {
    return () => setMinutes(2);
  }, [minutes == 0 && !timeDone]);

//HOURS

  //hours 24 => 0 (when minutes == 0)
  React.useEffect(() => {
    return () => setHours(hours - 1);
  }, [minutes == 0]);

  //hours == 23 (when hours == 0)
  React.useEffect(() => {
    return () => setHours(2);
  }, [hours == 0 && !timeDone]);

//DAYS
  //days 5 => 0 (when hours == 0)
  React.useEffect(() => {
      return () => setDays(days-1);
  }, [hours == 0 && !timeDone])

//DONE

  React.useEffect(() => {
      return () => setDone(true)
  }, [days == 0 && hours == 0 && minutes == 0 && seconds == 0])


  return (
    <div>
      <p>
        countdown: {days} : {hours} : {minutes} : {seconds}
      </p>
    </div>
  );
};
export default Countdown;

但它并没有像我预期的那样工作,+ 每次分钟数减少 2 分钟,小时数也是如此,似乎 useEffect 执行了 2 次,我不明白为什么。

你所有的useEffects其实都是运行宁2次

最初,您的 (seconds == 0) 为 false,当 seconds 变为 0 时变为 true,然后使用 Effect 运行 一次,您将其设置为 59,现在 (seconds == 0) 为 false useEffect 又是 运行 了。同样的事情会持续几分钟、几小时等等。当它们变为 0 和 59 时,useEffect 都是 运行。相反,您应该做的是仅当 bool cond 为 true

时才将值设置为 59

我认为这可以进一步简化为类似这样的内容。 您呈现的值仅取决于当前时间,其他一切都只是 this 时间相对于您的 timeLeft

的推导
function calculateTimeLeft() {
  const year = new Date().getFullYear();
  const difference = +new Date(`${year}-10-1`) - +new Date();
  let timeLeft = {};

  if (difference > 0) {
    timeLeft = {
      days: Math.floor(difference / (1000 * 60 * 60 * 24)),
      hours: Math.floor((difference / (1000 * 60 * 60)) % 24),
      minutes: Math.floor((difference / 1000 / 60) % 60),
      seconds: Math.floor((difference / 1000) % 60)
    };
  }

  return timeLeft;
}

export default function App() {
  const [timeLeft, setTimeLeft] = React.useState(calculateTimeLeft());

  React.useEffect(() => {
    const id = setTimeout(() => {
      setTimeLeft(calculateTimeLeft());
    }, 1000);

    return () => {
      clearTimeout(id);
    };
  });

  const timerComponents = Object.keys(timeLeft).map(interval => {
    if (!timeLeft[interval]) {
      return;
    }

    return (
       <span>
        {timeLeft[interval]} {interval}{" "}
      </span>
    )
  });

  return (
    <div>
      {timerComponents.length ? timerComponents : <span>Time's up!</span>}
    </div>
  );
}

您可以在此处查看工作示例 -> https://stackblitz.com/edit/react-t86icp