使用useEffect React Hook时如何解决缺少依赖项警告?

使用React 16.8.6(在以前的版本16.8.3中很好),当我尝试防止在获取请求上发生无限循环时,出现此错误

./src/components/BusinessesList.js
Line 51:  React Hook useEffect has a missing dependency: 'fetchBusinesses'.
Either include it or remove the dependency array  react-hooks/exhaustive-deps

我一直找不到停止无限循环的解决方案。我想远离使用useReducer()我确实在https://github.com/facebook/react/issues/14920找到了这个讨论,在这里可能的解决方案是You can always // eslint-disable-next-line react-hooks/exhaustive-deps if you think you know what you're doing.我不确定自己在做什么,所以我还没有尝试实现它。

我有这个当前设置,React钩子useEffect永远/无限循环连续运行,唯一的注释是useCallback()我不熟悉的。

我目前的使用方式useEffect()(类似于,我一开始只想运行一次componentDidMount()

useEffect(() => {
    fetchBusinesses();
  }, []);
const fetchBusinesses = () => {
    return fetch("theURL", {method: "GET"}
    )
      .then(res => normalizeResponseErrors(res))
      .then(res => {
        return res.json();
      })
      .then(rcvdBusinesses => {
        // some stuff
      })
      .catch(err => {
        // some error handling
      });
  };
乐米亚2020/03/12 12:45:54

只需在下一行禁用eslint即可;

useEffect(() => {
   fetchBusinesses();
// eslint-disable-next-line
}, []);

这样,您就可以像安装组件一样使用它(称为一次)

更新

要么

const fetchBusinesses = useCallback(() => {
 // your logic in here
 }, [someDeps])

useEffect(() => {
   fetchBusinesses();
// no need to skip eslint warning
}, [fetchBusinesses]); 

每当某些Dept更改时,都会调用fetchBusinesses

达蒙理查德2020/03/12 12:45:54

该解决方案也由react提供,他们建议您使用useCallback,这将返回函数的备注版本:

“ fetchBusinesses”函数使useEffect Hook(在第NN行)的依赖关系在每个渲染上都发生变化。要解决此问题,请将“ fetchBusinesses”定义包装到其自己的useCallback()中。Hook react-hooks / exhaustive-deps

useCallback使用简单,因为它具有相同的签名,useEffect不同之处在于useCallback返回一个函数。它看起来像这样:

 const fetchBusinesses = useCallback( () => {
        return fetch("theURL", {method: "GET"}
    )
    .then(// some stuff)
    .catch(// some error handling)
  }, [//deps])
  // We have a first effect thant uses fetchBusinesses
  useEffect(() => {
    // do things and then fetchBusinesses
    fetchBusinesses(); 
  }, [fetchBusinesses]);
   // We can have many effect thant uses fetchBusinesses
  useEffect(() => {
    // do other things and then fetchBusinesses
    fetchBusinesses();
  }, [fetchBusinesses]);
LEY宝儿2020/03/12 12:45:54

本文是使用钩子获取数据的良好入门:https : //www.robinwieruch.de/react-hooks-fetch-data/

本质上,在内部包含fetch函数定义useEffect

useEffect(() => {
  const fetchBusinesses = () => {
    return fetch("theUrl"...
      // ...your fetch implementation
    );
  }

  fetchBusinesses();
}, []);
阿飞神奇2020/03/12 12:45:54

况且什么在其他的答案已经提到(声明函数内useEffect,与memoize的它useCallback,您也可以直接将其设置为,禁止eslint的警告)useEffect回调:

useEffect(fetchBusinesses, [])

它只会触发一次,因此请确保正确设置了所有函数的依赖项(与使用相同componentDidMount/componentWillMount...


编辑02/21/2020

仅出于完整性考虑:

1.使用函数作为useEffect回调

useEffect(fetchBusinesses, [])

2.声明内部功能 useEffect()

useEffect(() => {
  function fetchBusinesses() {
    ...
  }
  fetchBusinesses()
}, [])

3.与 useCallback()

在这种情况下,如果函数中具有依赖项,则必须将它们包括在useCallback依赖关系数组中,useEffect如果函数的参数发生更改,这将再次触发依赖项此外,还有很多样板...因此只需直接将功能传递给useEffect1. useEffect(fetchBusinesses, [])

const fetchBusinesses = useCallback(() => {
  ...
}, [])
useEffect(() => {
  fetchBusinesses()
}, [fetchBusinesses])

4.禁用eslint的警告

useEffect(() => {
  fetchBusinesses()
}, []) // eslint-disable-line react-hooks/exhaustive-deps
GreenGil2020/03/12 12:45:54

您可以删除第二个参数类型数组,[]fetchBusinesses()每次更新都会调用。您可以根据需要IFfetchBusinesses()执行中添加一条语句

React.useEffect(() => {
  fetchBusinesses();
});

另一个是fetchBusinesses()在组件外部实现该功能。只是不要忘记将任何依赖项参数传递给您的fetchBusinesses(dependency)调用(如果有)。

function fetchBusinesses (fetch) {
  return fetch("theURL", { method: "GET" })
    .then(res => normalizeResponseErrors(res))
    .then(res => res.json())
    .then(rcvdBusinesses => {
      // some stuff
    })
    .catch(err => {
      // some error handling
    });
}

function YourComponent (props) {
  const { fetch } = props;

  React.useEffect(() => {
    fetchBusinesses(fetch);
  }, [fetch]);

  // ...
}
番长樱梅2020/03/12 12:45:54

如果除了效果以外没有在其他地方使用fetchBusinesses方法,则可以将其移至效果中并避免出现警告

useEffect(() => {
    const fetchBusinesses = () => {
       return fetch("theURL", {method: "GET"}
    )
      .then(res => normalizeResponseErrors(res))
      .then(res => {
        return res.json();
      })
      .then(rcvdBusinesses => {
        // some stuff
      })
      .catch(err => {
        // some error handling
      });
  };
  fetchBusinesses();
}, []);

但是,如果在渲染之外使用fetchBusinesses,则必须注意两点

  1. 有没有与你的任何问题,传递fetchBusinesses当它与它的外围封闭件支架中的二手的方法是什么?
  2. 您的方法是否依赖于从其封闭包中收到的某些变量?事实并非如此。
  3. 在每个渲染上,都会重新创建fetchBusinesses,因此将其传递给useEffect会引起问题。因此,如果要将fetchBusinesses传递给依赖项数组,则必须先记住它。

综上所述,我想说的是,如果您在fetchBusinesses外部使用,则可以使用useEffect禁用规则,// eslint-disable-next-line react-hooks/exhaustive-deps否则可以将方法移到useEffect内部

要禁用该规则,您可以这样写

useEffect(() => {
   // other code
   ...

   // eslint-disable-next-line react-hooks/exhaustive-deps
}, [])