gpt4 book ai didi

reactjs - 遵守 react-hooks/exhaustive-deps 会导致无限循环和/或大量 useCallback()

转载 作者:行者123 更新时间:2023-12-04 07:59:39 24 4
gpt4 key购买 nike

我的应用程序有一个 userService暴露了 useUserService与 API 函数 Hook ,例如 getUser , getUsers等。我为此使用了 Hook,因为 API 调用需要来自我的 Session 状态的信息,这些信息由 React Context Provider 提供。
提供getUsers函数到 useEffect调用react-hooks/exhaustive-deps eslint 规则不爽,因为它想要 getUsers列为 dep 的函数 - 但是,将其列为 dep 会导致效果在无限循环中运行,因为每次重新渲染组件时,它都会重新运行 useUserService钩子(Hook),它重新创建 getUsers功能。
这可以通过将函数包装在 useCallback 中来解决。 , 但随后 useCallback依赖数组遇到类似的 lint 规则。我想我一定是在这里做错了什么,因为我无法想象我应该将这些函数中的每一个都包含在 useCallback() 中。 .
我在 Codesandbox 中重新创建了这个问题。
1:遇到eslint警告:https://codesandbox.io/s/usecallback-lint-part-1-76bcf?file=/src/useFetch.ts
2:补救措施eslint洒水警告useCallback在,导致另一个 eslint警告:https://codesandbox.io/s/usecallback-lint-part-2-uwhhf?file=/src/App.js
3:解决方法eslint通过深入来统治:https://codesandbox.io/s/usecallback-lint-part-3-6wfwj?file=/src/apiService.ts
如果我只是忽略 lint 警告,一切都会正常工作......但我应该吗?

最佳答案

如果您想保留您已经选择的确切 API 和约束,这是规范的解决方案 — 你需要确保所有“一路向下”都有 useCallbackuseMemo周围。
所以不幸的是,这是正确的:

I can't imagine I'm supposed to wrap every single one of these functions in useCallback()


它有一个具体的实际原因。如果链的最底部的某些内容发生了变化(在您的示例中,这将是您所指的“来自 React 上下文的 session 状态”),您需要以某种方式将此更改传播到效果。否则他们会继续使用陈旧的上下文。
但是, 我的一般建议是首先尝试避免构建这样的 API .特别是,构建像 useFetch 这样的 API将任意函数作为回调,然后有效地调用它,提出了各种各样的问题。就像如果该功能在某些更改的状态下关闭,您希望发生什么?如果消费者传递一个总是“不同”的内联函数怎么办?如果您只尊重初始功能,当您获得 cond ? fn1 : fn2 时,您是否可以接受代码有问题?作为论据?
所以,一般来说,我强烈反对构建这样的帮助程序,而是重新考虑 API,这样您就不需要将“获取方式”注入(inject)数据获取函数,而是数据获取函数知道如何自己取。
TLDR:一个自定义 Hook 采用一个函数,然后在效果中需要它通常是不必要的通用,并导致像这样的并发症。

有关如何以不同方式编写此代码的具体示例:
  • 首先,在顶层写下您的 API 函数。不像 Hooks——只是简单的顶级函数。无论他们需要什么(包括“ session 上下文”)都应该在他们的论点中。
  • // api.js

    export function fetchUser(session, userId) {
    return axios(...)
    }
  • 创建 Hooks 以从 Context 中获取所需的任何数据。
  • function useSession() {
    return useContext(Session)
    }
  • 把这些东西组合在一起。
  • function useFetch(callApi) {
    const session = useSession()
    useEffect(() => {
    callApi(session).then(...)
    // ...
    }, [callApi, session])
    }
    import * as api from './api'

    function MyComponent() {
    const data = useFetch(api.fetchUser)
    }
    在这里, api.fetchUser从不“改变”,所以你没有任何 useCallback一点也不。
    编辑:我意识到我跳过了传递参数,比如 userId .您可以添加 args数组到 useFetch只接受可序列化的值,并使用 JSON.stringify(args)在您的依赖项中。您仍然必须禁用该规则,但至关重要的是 您遵守了规则的精神——指定了依赖关系 .这与为功能禁用它有很大不同,后者会导致细微的错误。

    关于reactjs - 遵守 react-hooks/exhaustive-deps 会导致无限循环和/或大量 useCallback(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66537226/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com