我正在做一个倒计时。简而言之,这个时钟将允许用户选择时间,当按钮启动时,它会倒计时。点击暂停会停止倒计时,取消会回到选择状态等。代码很大所以我放在这里
这个应用程序的问题是,当我点击“暂停”时,倒计时不会立即停止。它在停止之前仍然倒计时一个数字(例如,当在 5 处暂停时,它仍然倒计时到 4 并在 4 处停止)。
我试图找到错误,我猜错误仍然存在于components/time/index.js
. 下面是文件
import React, { useState, useEffect, useRef } from "react";
import Hour from "./Hour";
import Minute from "./Minute";
import Second from "./Second";
import { setTimeout } from "timers";
export default function Index({ runningMode, selectMode }) {
const [time, setTime] = useState({
hour: 0,
minute: 0,
second: 0
});
// GET value from the button
const getTime = name => value =>
setTime(oldValue => ({ ...oldValue, [name]: value }));
// COUNTDOWN setting
const tickDown = () => {
setTime(({ hour, minute, second }) => ({
hour: minute === 0 ? (second === 0 ? hour - 1 : hour) : hour,
minute: second === 0 ? (minute === 0 ? 59 : minute - 1) : minute,
second: second === 0 ? 59 : second - 1
}));
};
// Bug might be start here
// All console.log() below for the purpose of debug
const countDownRef = useRef();
useEffect(() => {
if (runningMode && time.hour >= 0) {
countDownRef.current = setTimeout(tickDown, 2000);
console.log("runningMode true");
}
if (!runningMode || time.hour < 0) {
clearTimeout(countDownRef.current);
console.log("runningMode wrong");
}
console.log("inside useEffect() ");
console.log(countDownRef.current);
console.log(time.second);
}, [runningMode, time]);
return (
<React.Fragment>
<Hour
setHour={getTime("hour")}
selectMode={selectMode}
time={time.hour}
/>
<Minute
setMinute={getTime("minute")}
selectMode={selectMode}
time={time.minute}
/>
<Second
setSecond={getTime("second")}
selectMode={selectMode}
time={time.second}
/>
</React.Fragment>
);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
这段代码在这部分表现得很奇怪useEffect()
,我猜这是错误的根源。奇怪的第一件事是setTimeout()
那里返回的不是整数,而是一个相似的对象 - 根据这个
我尝试的另一件事是更改setTimeout()
为setInterval()
. setInterval()
在这种情况下,返回一个整数 - 也反对文档,因为它应该与setTimeout()
. 更不用说使用setInterval()
使我们无法停止倒计时工作 - 按钮不起作用
这段代码中的第二个奇怪的事情是clearTimeout()
第一次调用时不起作用,然后下次调用。我试图跟踪执行的进度,当点击暂停时,它确实通过了clearTimeout()
并且没有通过setTimeout()
,但是超时并没有停止。我猜当点击暂停时传递给它的 timeoutID 会改变,但是当我注销该 ID 时它根本没有改变。
所以我被困在这里。猜猜它可以使用async/await解决,但我想知道为什么上面的这种方法会给出奇怪的结果。我还想知道如何修复这些错误以使应用程序按预期工作。谢谢