reactjs 为什么将变量的状态设置为常量数组变量会导致使用useEffect的无限循环?

snz8szmq  于 2023-06-22  发布在  React
关注(0)|答案(2)|浏览(136)

下面的代码会产生一个无限循环,使渲染达到最大。
我不知道为什么会这样。
我们在企业代码库中也有类似的问题,通过将常量数组更改为状态变量,使其不总是更改,并将其从useEffect中删除,因为它不会更改,已经解决了这个问题。
我猜,通过将y,一个不同的变量,设置为常量数组,它会导致重新渲染和x改变,因为指针值改变了?
我不确定,但我觉得这种行为很奇怪。

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="User Details" />, document.getElementById('root'));
izj3ouym

izj3ouym1#

事实与@Anubhav Raj的建议完全相反。
每次渲染组件时,x都是一个通过引用的全新数组。你可以用它调用setY,而不需要任何 Package 器(通常你会在useEffect中调用这些setter,或者用useCallback创建一个回调函数,但在这种情况下这并不重要,因为它总是会在每次渲染时发生)。
这样想吧:

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

这是两个不同的Array对象,尽管两者的元素相同。事实上,这是在同一个函数的两次不同运行中发生的,这使得很难推理,但本质上是相同的事情正在发生。
因为您正在用这个新值调用setY,这会使重新呈现排队,导致整个过程再次发生。
查看this post了解更多信息。

41zrol4v

41zrol4v2#

代码中的无限循环是由错误使用useState钩子和setY函数引起的。
在React中,useState钩子返回一个包含两个元素的数组:当前状态值和更新该状态值的函数。当调用setY(x)时,尝试将y的状态值更新为x。但是,由于x是一个常量数组[1001, 1002],因此无法更新。相反,您应该使用x的初始值初始化y

const [y, setY] = useState(x);

此外,在useEffect钩子中,您已经指定x作为依赖项。这意味着每当x更改时,效果就会运行。然而,由于x是一个不变的常量数组,因此效果将无限地运行,从而导致无限循环。
要解决这个问题,您可以从依赖数组中删除x,或者如果您想记录x的初始值一次,您可以传递一个空的依赖数组([]),以确保在组件装载时只运行一次效果:

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

下面是更新的代码:

import React, { useState, useEffect } from 'react';
import { render } from 'react-dom';

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

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

  return <div></div>;
};

render(<App />, document.getElementById('root'));

通过这些更改,代码应该不会再导致无限循环和过度渲染。

相关问题