[英]React Hooks useState+useEffect+event gives stale state
[英]React stale state with useEffect loop
给定以下组件:
import { useEffect, useState } from "react"
const Test = () => {
const [thing, setThing] = useState({ x: 0, y: 0 });
useEffect(() => {
gameLoop();
}, []);
const gameLoop = () => {
const p = {...thing};
p.x++;
setThing(p);
setTimeout(gameLoop, 1000);
}
return (
<div>
</div>
)
}
export default Test;
每秒都会在控制台中打印一个新行。 预期的 output 当然应该是:
{ x: 1, y: 0 }
{ x: 2, y: 0 }
{ x: 3, y: 0 }
...ETC
而是打印的是:
{ x: 0, y: 0 }
{ x: 0, y: 0 }
{ x: 0, y: 0 }
我得出结论,因为这是因为 state 过时。 我找到并尝试过的一些解决方案是:
将东西添加到依赖数组会导致它被快速调用。 将 thing.x 添加到数组中也是如此。
我发现一篇文章提到将 setState 更改为如下所示:
setState(thing => {
return {
...thing.
x: thing.x+1,
y: thing.y
});
这没有任何改变。
我发现了很多关于时钟/秒表的帖子,以及如何用原始值状态而不是对象来解决这个问题。
在保持它每秒只运行一次的同时修复行为的最佳行动方案是什么?
编辑:评论似乎是说我尝试这样的事情:
import { useEffect, useState } from "react"
const Test = () => {
const [thing, setThing] = useState({ x: 0, y: 0 });
useEffect(() => {
setInterval(gameLoop, 1000);
}, []);
const gameLoop = () => {
console.log(thing)
const p = {...thing};
p.x++;
setThing(prevP => ({...prevP, x: prevP.x+1}));
}
return (
<div>
</div>
)
}
export default Test;
这仍然打印不正确:
{ x: 0, y: 0 }
{ x: 0, y: 0 }
{ x: 0, y: 0 }
我认为您可以使用此解决方案:
useEffect(() => {
setInterval(() => {
setThing((prev) => ({
...prev,
x: prev.x + 1,
}));
}, 1000);
}, []);
我建议在组件被销毁时使用 clearInterval 控制 setInterval; 像这样:
useEffect(() => {
const interval = setInterval(() => {
setThing((prev) => ({
...prev,
x: prev.x + 1,
}));
}, 1000);
return () => {
clearInterval(interval);
};
}, []);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.