首页 > 解决方案 > 在 useEffect 中使用 setter 和 setInterval 时状态不更新

问题描述

我有以下代码,我希望它每 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>;
}

标签: reactjsuse-effectuse-state

解决方案


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

另一种方法是这样做:

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

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

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


推荐阅读