为什么 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);
}, []);

但是现在你会遇到另一个问题。间隔中使用的 numnumW 将锁定为组件第一次渲染时的值。

对于 num 你可以解决它,通过使用 setNum

callback 语法
useEffect(() => {
  setInterval(() => setNum(currentNum => currentNum += numW), 3000);
}, []);

但是numW永远不会更新。

最后一个工具是在每次 numWnum 更改时重置间隔。为此,您需要 return useEffect 中的一个函数来进行清算。

useEffect(() => {
  const interval = setInterval(() => setNum(currentNum => currentNum += numW), 3000);
  return () => clearInterval(interval);
}, [numW]);

但这会有一个小问题,即间隔现在不是恒定的,因为它会重置。