为什么 useEffect 依赖于被破坏的道具会导致超过最大更新?

Why does useEffect dependencies on destructed props cause maximum update exceeded?

我遇到了以下代码的问题:

function Test1(props) {
  const { ids = [] } = props;
  const [evenIds, setEvenIds] = useState<string[]>([]);

  useEffect(() => {
    const newEvenIds = ids.filter(id => id % 2 === 0);
    setEvenIds(newEvenIds);
  }, [ids])

  return (<span>hello</span>)
}

上面的代码使用了useEffect钩子监听props的变化。当这个组件被用作<Test1 ids={[]}/>时,一切似乎都很好。但是,如果不传props就作为<Test1 />使用,控制台会反复报错maximum update depth exceeded,最后浏览器崩溃。

我猜测初始值为 undefined 的变量 ids 被赋值 [],这导致 useEffect 变为 运行。但这如何导致重复错误?

ids 作为 prop 传递时,本地 ids 变量的引用唯一会在 prop 更改时更改。

当它不作为 prop 传递时,默认赋值,因为它在函数内部运行,每次函数运行时,每次都会产生一个新的空数组。因此,如果函数组件更新一次,它将尝试永远继续更新,因为默认的空数组引用不断变化。

解决此问题的一种方法是将空数组放在组件外部。 (只要确保不要像在 React 中一样发生变异)

const emptyArr = [];
function Test1(props) {
  const { ids = emptyArr } = props;
  const [evenIds, setEvenIds] = useState<string[]>([]);

  useEffect(() => {
    const newEvenIds = ids.filter(id => id % 2 === 0);
    setEvenIds(newEvenIds);
  }, [ids])

  return (<span>hello</span>)
}

尽管如此,状态不应在多个地方重复。 useMemo 比单独的州和 useEffect IMO 更合适。

const emptyArr = [];
function Test1(props) {
  const { ids = emptyArr } = props;
  const evenIds = useMemo(() => ids.filter(id => id % 2 === 0), [ids]);
  return (<span>hello</span>)
}

不是因为道具被破坏了。您正在使用一个类似于值的数组。

const { ids = [] } = props;

如果您想将该值用作数组,请尝试在您的 useEffect 中以这种方式使用它;

[JSON.stringfy(ids)]

useEffect 验证变量内的值并测试值是否改变。但是你需要在里面放一个原始值。如果你愿意,如果这个数组在所有位置都有原始值,你可以使用 ids[0] 来获得一个值。