Why will setting a state of a variable to a constant array variable cause an infinite loop with a useEffect?

huangapple go评论54阅读模式
英文:

Why will setting a state of a variable to a constant array variable cause an infinite loop with a useEffect?

问题

以下是翻译好的内容:

// 这段代码会产生一个无限循环,使渲染达到最大值。

// 我不确定为什么会发生这种情况。

// 在我们的企业代码库中也遇到了类似的问题,通过将常量数组更改为状态变量来解决,这样它就不会总是改变,并且将其从 useEffect 中移除,因为它不会改变。

// 我猜测通过将 y 这个不同的变量设置为一个常量数组,它会导致重新渲染,因为指针值发生了变化?

// 我不确定,但我觉得这种行为很奇怪。

import React, { Component, useState, useEffect, useCallback } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
import './style.css';

const App = (props) => {
  const [y, setY] = useState([]);
  const x = [1001, 1002];

  setY(x);

  useEffect(() => {
    console.log(x);
  }, [x]);

  return <div></div>;
};

render(<App appName="用户详情" />, document.getElementById('root'));
英文:

This code below produces an infinite loop, maxing out the rendering.

I'm unsure why this is happening.

We have a similar problem in our enterprise codebase that has been resolved by changing the constant array to a state variable so it doesn't always change and by removing it from the useEffect because it won't change.

I'm guessing that by setting y, a different variable, to a constant array, it causes a rerender and x changes because the pointer value changes?

I'm not sure but I find this behavior odd.

import React, { Component, useState, useEffect, useCallback } from &#39;react&#39;;
import { render } from &#39;react-dom&#39;;
import Hello from &#39;./Hello&#39;;
import &#39;./style.css&#39;;

const App = (props) =&gt; {
  const [y, setY] = useState([]);
  const x = [1001, 1002];

  setY(x);

  useEffect(() =&gt; {
    console.log(x);
  }, [x]);

  return &lt;div&gt;&lt;/div&gt;;
};

render(&lt;App appName=&quot;User Details&quot; /&gt;, document.getElementById(&#39;root&#39;));

答案1

得分: 2

事实与@Anubhav Raj所建议的完全相反。

每次组件重新渲染时,x都是一个全新的引用数组。而且你在没有任何包装的情况下调用了setY(通常你会在useEffect中调用这些setter,或者使用useCallback创建一个回调,但在这种情况下无论如何,它都会在每次渲染时发生)。

可以这样想:

let x = [1, 2];
x = [1, 2];

这是两个不同的数组对象,尽管两者的元素相同。这在同一个函数的两次不同运行中发生,使得理解起来有些困难,但本质上发生了相同的事情。

因为你用这个新值调用了setY,这会触发重新渲染,导致整个过程再次发生。

查看此文章获取更多信息。

英文:

The truth is exactly the opposite from what @Anubhav Raj suggests.

Each time your component renders, x is an entirely new array by reference. And you are calling setY with it without any kind of wrapper (usually you'll call these setters in useEffect or a callback you create with useCallback, but in this case it doesn't matter because it will always happen on every render anyway).

Think of it this way:

let x = [1, 2];
x = [1, 2];

These are two different Array objects, even though the elements of both are the same. The fact that this is happening in two different runs of the same function makes it difficult to reason about, but essentially the same thing is happening.

Because you're calling setY with that new value, that queues up a rerender, causing the whole process to happen again.

Check out this post for more info.

huangapple
  • 本文由 发表于 2023年6月19日 00:09:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/76501451.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定