为什么 setInterval 函数不能正常工作?
Why is the setInterval function not working properly?
一直显示死循环的错误信息。我才刚刚开始学习 React,这是一款 Clicker 游戏。如何更改我的代码以使 setInterval 起作用。谢谢。(顺便说一句,我不希望对不会影响 setInterval 函数的代码进行任何其他更改。是的,我已经在许多项目中使用过 setInterval,并且效果很好。)
import "./styles.css";
export default function App() {
let [num, setNum] = useState(0);
let [add, setAdd] = useState(1);
let [numC, setNumC] = useState(0);
let [numCP, setNumCP] = useState(10);
let [numW, setNumW] = useState(0);
let [numWP, setNumWP] = useState(20)
setInterval(setNum(num+=numW),3000);
const click = () => {
setNum((num += add));
};
const clicker = () => {
if (num >= numCP) {
setNumC((numC += 1));
setNum((num -= numCP));
setNumCP((numCP += 5));
setAdd((add += 1));
}
};
const worker = () => {
if (num >= numWP) {
setNumW((numW += 1));
setNum((num -= numWP));
setNumWP((numWP += 10));
}
};
return (
<div className="App">
<h1>Clicker Game</h1>
<div>
{num}
<button onClick={click}>Click</button>
</div>
<p />
<div>
{numC}
<button onClick={clicker}>Buy({numCP})</button>
</div>
<div>
{numW}
<button onClick={worker}>Buy({numWP})</button>
</div>
</div>
);
}```
每次您的状态变量之一发生变化时,组件就是 re-rendered,即再次调用函数 App
。这将一遍又一遍地调用 setInterval
。
您想查看 useEffect
以放入您的 setInterval
。
有几个问题。
首先,您应该立即调用 setNum
,而当您应该传递回调以在间隔结束时执行。
所以setInterval(() => setNum(num+=numW),3000);
但是现在你有第二个问题,每次组件 re-rendered 你都会启动一个额外的间隔。 (并且会 re-rendered 很多,至少每次触发间隔回调时 )
因此,您可能需要使用具有 0 个依赖项的 useEffect
,因此如果您想设置它并让它连续 运行,它会 运行 一次。
useEffect(() => {
setInterval(() => setNum(num += numW), 3000);
}, []);
但是现在你会遇到另一个问题。间隔中使用的 num
和 numW
将锁定为组件第一次渲染时的值。
对于 num
你可以解决它,通过使用 setNum
的 callback
语法
useEffect(() => {
setInterval(() => setNum(currentNum => currentNum += numW), 3000);
}, []);
但是numW
永远不会更新。
最后一个工具是在每次 numW
或 num
更改时重置间隔。为此,您需要 return useEffect
中的一个函数来进行清算。
useEffect(() => {
const interval = setInterval(() => setNum(currentNum => currentNum += numW), 3000);
return () => clearInterval(interval);
}, [numW]);
但这会有一个小问题,即间隔现在不是恒定的,因为它会重置。
一直显示死循环的错误信息。我才刚刚开始学习 React,这是一款 Clicker 游戏。如何更改我的代码以使 setInterval 起作用。谢谢。(顺便说一句,我不希望对不会影响 setInterval 函数的代码进行任何其他更改。是的,我已经在许多项目中使用过 setInterval,并且效果很好。)
import "./styles.css";
export default function App() {
let [num, setNum] = useState(0);
let [add, setAdd] = useState(1);
let [numC, setNumC] = useState(0);
let [numCP, setNumCP] = useState(10);
let [numW, setNumW] = useState(0);
let [numWP, setNumWP] = useState(20)
setInterval(setNum(num+=numW),3000);
const click = () => {
setNum((num += add));
};
const clicker = () => {
if (num >= numCP) {
setNumC((numC += 1));
setNum((num -= numCP));
setNumCP((numCP += 5));
setAdd((add += 1));
}
};
const worker = () => {
if (num >= numWP) {
setNumW((numW += 1));
setNum((num -= numWP));
setNumWP((numWP += 10));
}
};
return (
<div className="App">
<h1>Clicker Game</h1>
<div>
{num}
<button onClick={click}>Click</button>
</div>
<p />
<div>
{numC}
<button onClick={clicker}>Buy({numCP})</button>
</div>
<div>
{numW}
<button onClick={worker}>Buy({numWP})</button>
</div>
</div>
);
}```
每次您的状态变量之一发生变化时,组件就是 re-rendered,即再次调用函数 App
。这将一遍又一遍地调用 setInterval
。
您想查看 useEffect
以放入您的 setInterval
。
有几个问题。
首先,您应该立即调用 setNum
,而当您应该传递回调以在间隔结束时执行。
所以setInterval(() => setNum(num+=numW),3000);
但是现在你有第二个问题,每次组件 re-rendered 你都会启动一个额外的间隔。 (并且会 re-rendered 很多,至少每次触发间隔回调时 )
因此,您可能需要使用具有 0 个依赖项的 useEffect
,因此如果您想设置它并让它连续 运行,它会 运行 一次。
useEffect(() => {
setInterval(() => setNum(num += numW), 3000);
}, []);
但是现在你会遇到另一个问题。间隔中使用的 num
和 numW
将锁定为组件第一次渲染时的值。
对于 num
你可以解决它,通过使用 setNum
callback
语法
useEffect(() => {
setInterval(() => setNum(currentNum => currentNum += numW), 3000);
}, []);
但是numW
永远不会更新。
最后一个工具是在每次 numW
或 num
更改时重置间隔。为此,您需要 return useEffect
中的一个函数来进行清算。
useEffect(() => {
const interval = setInterval(() => setNum(currentNum => currentNum += numW), 3000);
return () => clearInterval(interval);
}, [numW]);
但这会有一个小问题,即间隔现在不是恒定的,因为它会重置。