使用 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() 。我确实找到了这个讨论 [ESLint] 对 ‘exhaustive-deps’ lint rule #14920 的反馈, 其中一个可能的解决方案是 You can always // eslint-disable-next-line react-hooks/exhaustive-deps if you think you know what you're doing. 我对自己在做什么没有信心,所以我没有尝试实施它只是还没有。

我有这个当前设置, _ React hook 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
      });
  };

原文由 russ 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 3.1k
2 个回答

如果您没有在效果之外的任何地方使用 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 禁用规则,否则您可以将方法移到 useEf

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

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

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

原文由 Shubham Khatri 发布,翻译遵循 CC BY-SA 4.0 许可协议

如果您正在创建新应用程序或具有足够的灵活性,则状态管理库有很好的选择。检查后坐力。

只是为了完整性:

1. (停止工作) 使用函数作为 useEffect 回调

useEffect(fetchBusinesses, [])

2.在里面声明函数 useEffect()

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

3. 记忆 useCallback()

在这种情况下,如果函数中有依赖项,则必须将它们包含在 useCallback 依赖项数组中,如果函数的参数发生变化,这将再次触发 useEffect 。此外,它有很多样板…所以只需将函数直接传递给 useEffect 就像 1. useEffect(fetchBusinesses, []) 一样。

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

4.函数的默认参数

正如 Behnam Azimi 所建议的

这不是最佳做法,但在某些情况下可能会有用。

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

5.创建自定义钩子

创建一个自定义挂钩并在您只需要运行一次函数时调用它。它可能更干净。您还可以在需要时返回回调以重置重新运行“初始化”。

 // customHooks.js
const useInit = (callback, ...args) => {
  const [mounted, setMounted] = useState(false)

  const resetInit = () => setMounted(false)

  useEffect(() => {
     if(!mounted) {
        setMounted(true);
        callback(...args);
     }
  },[mounted, callback]);

  return [resetInit]
}

// Component.js
return ({ fetchBusiness, arg1, arg2, requiresRefetch }) => {
  const [resetInit] = useInit(fetchBusiness, arg1, arg2)

  useEffect(() => {
    resetInit()
  }, [requiresRefetch, resetInit]);

6.禁用eslint的警告

禁用警告应该是你最后的手段,但当你这样做时,最好 内联并显式地 进行,因为未来的开发人员可能会感到困惑或在不知道 linting 已关闭的情况下产生意想不到的错误

useEffect(() => {
  fetchBusinesses()
}, []) // eslint-disable-line react-hooks/exhaustive-deps

原文由 jpenna 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题