如何修复React Hook useEffect中缺少的依赖项

问题描述 投票:10回答:6

使用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 hook useEffect runs continuously forever/infinite loop和唯一的评论是关于我不熟悉的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
      });
  };
reactjs eslint create-react-app react-hooks
6个回答
12
投票

如果你没有在效果之外的任何地方使用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作为方法,并且在mount期间使用它的封闭闭包将没有任何问题,如果有任何问题。
  2. 你的方法是否依赖于它从封闭闭包中收到的一些变量,而你的情况并非如此。
  3. 在每次渲染时,将重新创建fetchBusinesses,因此将其传递给useEffect将导致问题。因此,如果要将fetchBusinesses传递给依赖关系数组,首先必须记住fetchBusinesses。

总结一下,我会说如果你在fetchBusinesses之外使用useEffect你可以使用// eslint-disable-next-line react-hooks/exhaustive-deps禁用规则,否则你可以在useEffect中移动方法

要禁用规则,您可以像写一样

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

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

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

这不是JS / React错误,而是eslint警告。

它告诉你钩子依赖于函数fetchBusinesses,所以你应该把它作为依赖传递。

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

如果fetchBusinessess在运行中没有组件,那将不会真正改变任何事情,但警告将消失。

更多:https://github.com/facebook/react/issues/14920


2
投票

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

基本上,在useEffect中包含fetch函数定义:

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

  fetchBusinesses();
}, []);

0
投票

您可以删除第二个参数类型数组[],但每次更新时也会调用fetchBusinesses()。如果您愿意,可以在IF实现中添加fetchBusinesses()语句。

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]);

  // ...
}

0
投票

解决方案也是反应,他们建议您使用useCallback,它将返回您的函数的memoize版本:

'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]);

-2
投票

只需禁用下一行的eslint;

useEffect(() => {
   fetchBusinesses();
// eslint-disable-next-line
}, [fetchBusinesses]);
© www.soinside.com 2019 - 2024. All rights reserved.