尝试使用 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
正如标题所说,我正在尝试创建一个从
开始的倒计时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