我刚刚开始学习react,并且正在观看有关状态和挂钩的教程。它仅处理每1000毫秒的更新时间(或者我认为)。
import React from "react";
let count = 0;
function App() {
const now = new Date().toLocaleTimeString();
let [time, setTime] = React.useState(now);
function updateTime(){
const newTime = new Date().toLocaleTimeString();
setTime(newTime);
count++;
console.log(count);
console.log(new Date().getMilliseconds());
}
setInterval(updateTime, 1000);
return (
<div className="container">
<h1>{time}</h1>
<button onClick = {updateTime}>time</button>
</div>
);
}
export default App;
本教程的目的只是一个有关如何更新时间的简单示例,但我注意到的是,它每1000毫秒更新一次(突发)多次。我怀疑每次更改挂钩都会出现新组件,但是旧组件仍在更新并产生更多组件,从而导致每1000毫秒的调用次数呈指数增长。
我很好奇,这是怎么回事?我该如何说一个简单的计数器每1000毫秒更新一次?setTime(count)
显然不起作用
问题是:在当前的实现中,setInterval
每次渲染组件时都会调用(即,在设置时间状态后也会调用),并且会创建一个新的间隔-产生这种“指数增长”,如在控制台中所见。
如评论部分所述:useEffect
在React中处理功能组件时,这是处理此场景的最佳方法。看下面我的例子。useEffect
仅在渲染初始组件后(安装组件时)才运行此命令。
React.useEffect(() => {
console.log(`initializing interval`);
const interval = setInterval(() => {
updateTime();
}, 1000);
return () => {
console.log(`clearing interval`);
clearInterval(interval);
};
}, []); // has no dependency - this will be called on-component-mount
如果要运行效果并仅将其清理一次(在挂载和卸载时),则可以传递一个空数组([])作为第二个参数。这告诉React您的效果不依赖于道具或状态的任何值,因此它不需要重新运行。
在您的方案中,这是“空数组作为第二个参数”的完美用法,因为您只需要在安装组件时设置间隔,而在卸载组件时清除间隔。看一下useEffect
返回的函数。这是我们的清理功能,将在卸载组件时运行。这将“清理”或在这种情况下,清除不再使用组件的时间间隔。
我编写了一个小应用程序,演示了我在此答案中涵盖的所有内容:https : //codesandbox.io/s/so-react-useeffect-component-clean-up-rgxm0?file=/ src/ App.js
我并入了一个小的路由功能,以便可以观察到组件的“卸载”。
我的旧答案(不推荐):
每次重新渲染组件时都会创建一个新的时间间隔,这是您为时间设置新状态时发生的情况。我要做的是clearInterval
在设置新间隔之前清除上一个间隔()
try {
clearInterval(window.interval)
} catch (e) {
console.log(`interval not initialized yet`);
}
window.interval = setInterval(updateTime, 1000);
https://developer.mozilla.org/zh-CN/docs/Web/API/WindowOrWorkerGlobalScope/setInterval
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句