【问题标题】:State not update when using setter and setInterval in useEffect在 useEffect 中使用 setter 和 setInterval 时状态不更新
【发布时间】:2021-07-14 00:18:32
【问题描述】:

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

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

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

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

【问题讨论】:

  • 这是因为 setDigits(data); 使用数组做到这一点 setDigits([...data]);。工作示例:codesandbox.io/s/crazy-kapitsa-cp5qf?file=/src/App.js 或者更好的是,删除 data 蚂蚁只需执行 let timer = setInterval(() =&gt; { setDigits([...digits, 10]); }, 2000);
  • @Lith 你能提供一个带有解释的答案以便我接受吗?

标签: reactjs use-effect use-state


【解决方案1】:

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

另一种方法是这样做:

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

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

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

【讨论】:

    【解决方案2】:

    在您的代码中,您通过在每个 2 秒后推送 10 来改变相同的数组 data。因此,useEffect 不会在后续渲染中执行。因此,要么像下面的代码 sn-p 那样传播 data 数组,要么像 Lith 建议的那样简单地摆脱 data 变量并依赖 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>;
    }
    

    【讨论】:

    • 但是data的内容每2秒变化一次,我把它包含在了依赖数组中,为什么useEffect没有拾取变化?
    • 是的,它改变了。但是push 修改了相同的数组,导致相同的引用。 concat[...] 的情况正好相反。
    猜你喜欢
    • 2021-01-17
    • 2022-01-24
    • 2020-10-20
    • 2019-04-01
    相关资源
    最近更新 更多