我正在尝试创建一个时钟,它将每秒钟运行一次,但也允许用户单击按钮将时钟向前移动一小时。
const addTime = (date, time) => new Date(date.getTime() + time)
const Clock = () => {
const [timeDate, setTimeDate] = useState(addTime(new Date(), SECOND_IN_MS));
const updateTimeInfo = (addedTime) => {
setTimeDate(addTime(timeDate, addedTime);
//other info omitted, won't affect the code
}
useEffect(() => {
let tickClock = setInterval(() => {
updateTimeInfo(SECOND_IN_MS)
}, SECOND_IN_MS);
return () => clearInterval(tickClock);
}, [timeDate])
return (
<span>{timeDate.toLocaleTimeString([], { hour: '2-digit', hour12: true, minute: '2-digit' });</span>
<button type="button" onClick={() => updateTimeInfo(HOUR_IN_MS)}>{"Add 1 hour"}</button>
)
}
现在的问题是,每当我将时钟更新为新的时间时,就会触发useEffect,并且时钟将重新建立每秒钟更新一次的间隔,导致时钟在1秒过去之前不会更新秒。
我希望时钟总是滴答1秒,但也允许用户同时快速前进1小时。
有可能让这一切成为可能吗?
发布于 2020-12-04 01:27:37
从timeDate
钩子中删除useEffect
依赖项,并在updateTimeInfo
中使用功能状态更新。
timeDate
状态更新从前一个状态正确更新。
const updateTimeInfo = (addedTime) => { setTimeDate((timeDate) => addTime(timeDate,addedTime));//其他省略的信息,不会影响代码};它的工作原理:
间隔每秒运行一次updateTimeInfo
。该按钮也只是以异步方式调用updateTimeInfo
,即每当单击+1小时按钮时。这两者应该是相互独立的。
如果没有函数状态更新,那么只有初始的timeDate
状态值在效果上被关闭,而时间只会从初始状态值每次更新一次。
代码
const SECOND_IN_MS = 1000;
const HOUR_IN_MS = 1000 * 60 * 60;
const addTime = (date, time) => new Date(date.getTime() + time);
const Clock = () => {
const [timeDate, setTimeDate] = useState(addTime(new Date(), SECOND_IN_MS));
const updateTimeInfo = (addedTime) => {
setTimeDate((timeDate) => addTime(timeDate, addedTime));
//other info omitted, won't affect the code
};
useEffect(() => {
const tickClock = setInterval(() => {
updateTimeInfo(SECOND_IN_MS);
}, SECOND_IN_MS);
return () => clearInterval(tickClock);
}, []);
return (
<>
<span>
{timeDate.toLocaleTimeString([], {
hour: "2-digit",
hour12: true,
minute: "2-digit",
second: "2-digit"
})}
</span>
<button type="button" onClick={() => updateTimeInfo(HOUR_IN_MS)}>
+1 hour
</button>
<button type="button" onClick={() => updateTimeInfo(-HOUR_IN_MS)}>
-1 hour
</button>
</>
);
};
https://stackoverflow.com/questions/65140518
复制