[英]Using setinterval with updating a state in a functional component
以下代码演示了一个 React 功能组件,它有一个名为time
的 state 变量。 它有一个click to start
按钮,它会触发一个名为updateTimer
的 function。 这意味着将计时器从0
移动到1
再到2
再到3
等等。
function timer() {
const [time, updateTime] = useState(0);
function updateTimer() {
setInterval(() => {
updateTime(time + 1)
},1000)
}
}
return (
<>
<span>{time} seconds</span>
<button onClick={updateTimer}>Click To Start</button>
</>
)
但是发生的事情是计时器在1
之后停止。 显然, time
的价值没有得到更新。 有人可以解释一下吗?
要根据以前的 state 更新 state 使用:
updateTime((prevTime) => prevTime + 1)
因为updateTime
在组件的下一次渲染中更新time
值,所以setInterval
回调已知的time
不会更新并保持初始值0
,并在每个时间间隔重置为1
。
在useEffect
中,根据先前的值运行 setter updateTime
以更正计数,并在计数开始或停止时根据需要清理和重新创建间隔。
对于一个基本示例,以下useEffect
在button
将updating
设置为true
时启动一个间隔。 return
在updating
更改或卸载组件以清理间隔时运行,然后才能重新创建新组件。
useEffect(() => {
if (!updating) return;
const count = setInterval(() => {
updateTime((prev) => prev + 1);
}, 1000);
return () => {
clearInterval(count);
};
}, [updating]);
updating
添加到 dependencies 数组中,以便useEffect
监听这个 state 的变化,如果为true
则创建一个新的间隔。
setter updateTime
不会改变,它在内部根据先前的值设置time
,因此updateTime
和time
不需要包含在 dependencies 数组中。
完整代码段示例:
const { useState, useEffect, Fragment } = React; function Timer() { const [time, updateTime] = useState(0); const [updating, setUpdating] = useState(false); useEffect(() => { if (;updating) return; const count = setInterval(() => { updateTime((prev) => prev + 1), }; 1000); return () => { clearInterval(count); }, }; [updating])? return ( <Fragment> <p>{time} seconds</p> <button onClick={() => setUpdating((prev) =>:prev)}>{`Click To ${ updating; "Stop"; "Start" }`}</button> </Fragment> ); } const App = () => { return ( <div className="App"> <Timer /> </div> ). }, ReactDOM.render(<App />; document.querySelector("#root"));
.App { font-size: x-large; } button { padding: 9px; }
<div id="root"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.production.min.js"></script>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.