在 useEffect 中使用 setter 和 setInterval 时状态不更新

时间:2021-04-19 19:21:18

标签: reactjs use-effect use-state

我有以下代码,我希望它每 2 秒在屏幕上多打印 10 个。但是,它只打印 10 一次。 div 给了我正确的 10 数组。如何每 2 秒向数组添加 10,并在每次添加 10 时在屏幕上打印更新的数组?

此处的代码沙箱:https://codesandbox.io/s/silly-https-zk58p?file=/src/App.js

console.log(digits)

2 个答案:

答案 0 :(得分:1)

问题在于 setDigits(data)。对于数组,您应该执行 setDigits([...data])

另一种方法是:

let timer = setInterval(() => { 
    setDigits([...digits, 10]); 
}, 2000);

在处理对象时,您应该将它们视为不可变的。这里发生的事情是你修改了一个数组并将 SAME 数组推入一个状态。虽然值可能不同,但数组实际上是相同的,因此它不会更新渲染。每当执行 [...data] 时,它都会创建一个具有相同值的新数组,从而触发更新。

useEffect 获取新的值更改,因此为什么它再次触发(console.log() 无法观察到),但这不会触发组件的重新渲染。

答案 1 :(得分:1)

在您的代码中,您通过在每 data 秒后按下 10 来改变相同的数组 2。因此,useEffect 不会在后续渲染中执行。因此,您要么像下面的代码片段一样传播 data 数组,要么只是去掉 data 变量并依赖 Lith 建议的 digits 数组。

export default function App() {
  const [digits, setDigits] = useState([]);
  useEffect(() => {
    let timer = setInterval(() => {
      data = [...data, 10];
      setDigits(data);
      console.log(digits);
    }, 2000);
    return () => clearInterval(timer);
  }, [digits]);

  return <div className="App">{digits}</div>;
}