luk*_*eau 7 reactjs react-hooks
我的应用程序有一个userService公开useUserService带有 API 函数(例如getUser、getUsers等)的钩子。我为此使用钩子是因为 API 调用需要来自我的会话状态的信息,该信息由 React Context Provider 提供。
getUsers向调用提供函数useEffect会使react-hooks/exhaustive-depseslint 规则不满意,因为它希望将getUsers函数列为 dep - 但是,将其列为 dep 会导致效果在无限循环中运行,因为每次重新渲染组件时,它都会重新运行useUserService钩子,从而重新创建该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:通过更深入地补救该规则: https://codesandbox.io/s/usecallback-lint-part-3-6wfwj ?file=/src/apiService.tseslint
如果我忽略 lint 警告,一切都会正常工作......但我应该吗?
如果您想保留您已经选择的确切 API 和约束,那就是规范的解决方案\xe2\x80\x94,您需要确保“一直向下”的所有内容都具有useCallback或useMemo围绕它。
不幸的是,这是正确的:
\n\n\n我无法想象我应该将这些函数中的每一个都包装在 useCallback() 中
\n
这是有具体实际原因的。如果链最底部的某些内容发生变化(在您的示例中,这将是您所指的“React 上下文中的会话状态”),您以某种方式需要此更改来传播效果。否则他们会继续使用陈旧的上下文。
\n然而,我的一般建议是首先尝试避免构建这样的 API。特别是,构建这样的 APIuseFetch将任意函数作为回调,然后有效地调用它,会带来各种各样的问题。就像如果该函数在某些状态发生变化时关闭,您希望发生什么?如果消费者传递一个总是“不同”的内联函数怎么办?cond ? fn1 : fn2如果您只尊重初始功能,那么当您将其作为参数时,您是否可以接受代码有错误?
因此,一般来说,我强烈建议不要构建这样的助手,而是重新考虑 API,这样您就不需要将“获取方式”注入到数据获取函数中,而数据获取函数知道如何执行自行获取。
\nTLDR:自定义 Hook 获取效果中需要的函数通常是不必要的通用,并会导致像这样的复杂性。
\n有关如何以不同方式编写此内容的具体示例:
\n// api.js\n\nexport function fetchUser(session, userId) {\n return axios(...)\n}\nRun Code Online (Sandbox Code Playgroud)\nfunction useSession() {\n return useContext(Session)\n}\nRun Code Online (Sandbox Code Playgroud)\nfunction useFetch(callApi) {\n const session = useSession()\n useEffect(() => {\n callApi(session).then(...)\n // ...\n }, [callApi, session])\n}\nRun Code Online (Sandbox Code Playgroud)\n和
\nimport * as api from \'./api\'\n\nfunction MyComponent() {\n const data = useFetch(api.fetchUser)\n}\nRun Code Online (Sandbox Code Playgroud)\n在这里,永远不会“改变”,所以你根本api.fetchUser没有任何改变。useCallback
编辑:我意识到我跳过了传递参数,比如userId. 您可以添加一个仅接受可序列化值的args数组,并在依赖项中使用。您仍然必须禁用该规则,但最重要的是您遵守规则的精神 \xe2\x80\x94 依赖项已指定useFetchJSON.stringify(args)。这与禁用它的功能有很大不同,后者会导致微妙的错误。
| 归档时间: |
|
| 查看次数: |
2410 次 |
| 最近记录: |