我想弄清楚,何时useEffect导致重新渲染。以下示例的结果使我感到非常惊讶:

https://codesandbox.io/embed/romantic-sun-j5i4m

function useCounter(arr = [1, 2, 3]) {
  const [counter, setCount] = useState(0);
  useEffect(() => {
    for (const i of arr) {
      setCount(i);
      console.log(counter);
    }
  }, [arr]);
}

function App() {
  useCounter();
  console.log("render");
  return <div className="App" />;
}

该示例的结果如下:

reactjs - useEffect Hook示例:是什么原因导致重新渲染?-LMLPHP

我的困惑来自两件事:我不知道为什么:
  • 组件仅渲染3次(我​​猜想组件每次调用setCount都会重新渲染+一个初始渲染-因此是4次)
  • 计数器永远只有两个值0和3:我猜想,正如此article所述,每个渲染器都看到自己的状态和 Prop ,因此整个循环将以每个状态作为常量(1、2、3)运行- >但是为什么国家永远不会2?

  • 如果有人能澄清我将非常高兴。谢谢!

    最佳答案

    我将尽力解释(或逐步进行)正在发生的事情。我还在第7点和第10点做两个假设。

  • 应用程序组件安装。
  • 挂载后调用
  • useEffect
  • useEffect将“保存”初始状态,因此,只要在内部引用,counter将为0。
  • 循环运行3次。每次迭代setCount都被调用以更新计数,并且控制台日志记录根据“存储”版本为0的计数器。因此,数字0在控制台中记录了3次。因为状态已更改(0-> 1、1-> 2、2-> 3),所以React集就像一个标志或一些要告诉自己要记住要重新渲染的东西。
  • React在执行useEffect时未重新渲染任何内容,而是等待useEffect完成后重新渲染。
  • 完成useEffect后,React会记住counter的状态在其执行过程中已更改,因此它将重新呈现该应用程序。
  • 应用程序重新渲染,并再次调用useCounter。请注意,这里没有参数传递给useCounter自定义钩子(Hook)。
    假设:我自己也不知道,但是我认为默认参数似乎是重新创建的,或者至少以某种方式使React认为它是新的。因此,由于arr被视为新的,因此useEffect挂钩将再次运行。这是我可以解释第二次运行的useEffect的唯一原因。
  • 在第二次运行useEffect期间,counter的值为3。控制台日志将按预期方式记录3的数字3。
  • 再次运行useEffect后,React发现计数器在执行过程中发生了变化(3-> 1,1-> 2,2-> 3),因此该应用将重新渲染,从而导致第三个“渲染”日志。
  • 假设:,因为从应用程序的 Angular 来看,useCounter挂钩的内部状态在此渲染与前一个渲染之间没有变化,因此它不执行其中的代码,因此第三次不调用useEffect。因此,应用程序的第一个渲染将始终运行挂钩代码。应用程序第二次看到钩子(Hook)的内部状态从0变为3,因此决定重新运行它,第三次应用程序看到钩子(Hook)的内部状态为3仍然为3,因此决定不执行该操作。重新运行它。这是我可以提出的使钩子(Hook)不再运行的最好原因。您可以在挂钩本身中放入日志,以查看它实际上并没有第三次运行。

  • 这就是我所看到的,我希望这可以使它更加清晰。

    10-06 08:06
    查看更多