React useEffect 包括缺少的依赖项将破坏它

React useEffect including the missing dependency will break it

我正在开发带有一些 useEffect 钩子的 React 应用程序。假设我有以下代码:

import React, { useState, useEffect } from 'react';

export default () => {
  const [fooArr, setFooArr] = useState([]);
  const [barObj, setBarObj] = useState({});

  return <h1>{barObj.name + " " + barObj.status}</h1>
}

但是,问题来了。 fooArr 在其他地方发生了变化,我想在 fooArr 发生变化时更新 barObj。我这样做如下:

import React, { useState, useEffect } from 'react';

export default () => {
  const [fooArr, setFooArr] = useState([]);
  const [barObj, setBarObj] = useState({});

  // >>> some fetching and setting of 'fooArr' here <<<

  useEffect(() => {
    setBarObj(barObj => {
      let _barObj = { ...barObj };
      _barObj.status = fooArr[1];
      return _barObj;
    })
  }, [fooArr]);

  return <h1>{barObj.name + " " + barObj.status}</h1>
}

但是,这给了我以下错误 React Hook useEffect has a missing dependency: 'barObj' and 'setBarObj'. Either include it or remove the dependency array。我确切地知道这意味着什么,但是当我包含它时,我得到了一个无限的重新渲染循环,因为它不断更新自己。我现在在依赖数组旁边有 // eslint-disable-line 来忽略它。但我觉得永远不应该这样做。

我该如何处理?我不想收到错误消息,但也不想无限重新渲染循环..

包含更多代码的示例,类似于我的代码:

useEffect(() => {
  setBarObj(prevBarObj => {
    let _barObj = { ...prevBarObj };
    if(_barObj.status.includes('hello') {
      _barObj.status += "world"
    } else {
      _barObj.status = "other"
    }
    return _barObj;
  })
}, [fooArr])

我认为显示缺少依赖项警告是因为您正在从状态中隐藏 barObj。尝试使用不同的参数名称并避免对象复制:

useEffect(() => {
    setBarObj(bar => {
      return {...bar, status: fooArr[1]};
    })
  }, [fooArr]);

这应该可以正常工作:

useEffect(() => {
  setBarObj(barObj => ({
    ...barObj,
    status: fooArr[1]
  })
}, [fooArr]);

我还建议您查看我的另一个 以解决获取数据的问题并避免丢失依赖项错误。


根据您的评论,您可以这样做:

useEffect(() => {
  if (barObj.status === 'hello') return
  setBarObj(barObj => ({
    ...barObj,
    status: fooArr[1]
  })
}, [fooArr]);

使用更新后的查询,您可以使用:

useEffect(() => {
  setBarObj(barObj => {
    const updatedStatus = barObj.status === 'hello' ? (barObj.status + 'world') : fooArr[1]
    return {
    ...barObj,
    status: updatedStatus
  }
}, [fooArr]);