【问题标题】:react custom hooks vs normal functions, what is the difference反应自定义钩子与普通功能,有什么区别
【发布时间】:2020-05-24 18:26:49
【问题描述】:

我正试图围绕自定义挂钩。我理解普通的钩子很好,但我的问题是,在编写自定义钩子时,它和普通函数有什么区别?我的意思是为什么不称它为普通函数而不是像 use* 之类的调用它

【问题讨论】:

    标签: reactjs react-hooks


    【解决方案1】:

    一个自定义钩子依赖于另外一个钩子。按照设计,React 钩子旨在从组件的渲染方法中使用。如果您尝试在其他任何地方使用钩子,您将收到警告。自定义挂钩遵循与内置挂钩相同的约定,因为它们必须以相同的方式使用。 use 前缀只是一个约定,用于标识通常在组件渲染方法的最顶部调用的钩子函数。

    你可以为你的钩子函数命名任何你想要的名字,但正如我所提到的,如果在渲染方法之外使用,你会收到来自 React 的警告。

    【讨论】:

    • 也许我遗漏了一些东西,但除了关于钩子的documentation and rules 之外,仅将其称为普通旧函数(除了 linting 功能)有什么优势?
    • 是的。您错过了建议的事实,因此您可以轻松识别挂钩与其他功能。话虽如此,您可以随意命名您的函数。
    • 所以假设我将一个钩子命名为 myCustomFunction 而不是命名为 useCustomFunction,所以除了 linting 和其他记录在案的规则之外,我不会失去任何功能吗?
    • 没有。您不会失去任何功能。只是一个函数。但是就像我说的,由于自定义钩子通常由其他钩子组成,如果你在上下文之外使用你的函数,你会得到一个错误,但这与函数名本身无关。
    【解决方案2】:

    来自 React docs

    自定义 Hook 是一个 JavaScript 函数,其名称以“use”开头,并且可以调用其他 Hook。 [...] 它的名称应始终以“use”开头,以便您一眼就能看出rules of Hooks 适用于它。

    那么为什么要使用特殊的“使用”命名前缀来定义自定义 Hook?

    1.) 它告诉消费者,这些函数旨在与 React 一起使用并遵守隐式合同(上述规则)。

    2.) 您可以获得检查和执行这些规则的工具支持。例如,eslint-plugin-react-hooks 使用 heuristic 假设函数以“use”前缀开头,后面是大写字母是 Hook。

    【讨论】:

    • 这是正确答案。自定义挂钩是一种功能,其使用受挂钩规则的约束,就像内置挂钩一样。由于自定义钩子通常包含钩子本身,因此我们必须确保仅在通常使用钩子合法的地方才调用自定义钩子。
    【解决方案3】:

    React Hooks(自定义或非自定义)应该以 use 前缀开头。以及,根据 React 文档:

    1) Hooks 只能从 React 代码调用,而不是从常规 JS 函数调用。因此,Hooks 的范围仅限于 React 代码世界,并且有更多的能力来处理 React 代码。与 JS 不同,常规函数可以跨应用程序使用,但由于 React 代码指南使代码更符合 React 语法。

    2) 在基于类的组件中,Hooks 不起作用,但常规函数可以。

    3) 在常规 JS 函数中,您无法访问 useStateuseEffectuseContext 等,但在 react 自定义挂钩中我可以。

    【讨论】:

    • 在名称后附加“使用”不是强制性的。鉴于函数的首字母大写,即反应函数,我仍然可以使用 useState、useEffect 等。看到这个前:codesandbox.io/s/react-playground-crjbf?file=/index.js
    • 是的,但是 ReactJS 钩子的最佳实践建议它应该从“使用”开始。
    【解决方案4】:

    我相信没有人准确地回答您的问题。我仍然理解拥有这个称为钩子的额外功能的好处和目的,但我仍然可以分享我的理解。

    React Hooks 是具有 react 能力的 JS 函数,这意味着你可以添加一些逻辑,你也可以添加到普通的 JS 函数中,但你也可以使用原生的钩子,如 useState、useEffect 等,以启动该逻辑,为其添加状态,或为其添加副作用,记忆或更多。 所以我相信 hooks 是一个非常好的以隔离方式管理组件逻辑的东西。

    因此,您可以有一个 foo.component.js (UI)、一个 useFoo.js(logic),其中 useFoo 可能包含许多 js 函数和一个用于管理这些函数并返回其应有内容的钩子。

    这是一个关于 React hooks 的精彩视频,强烈推荐

    https://youtu.be/J-g9ZJha8FE

    【讨论】:

    • 感谢分享,正是我想要的!
    • 所以基本上,如果你的 callable 不需要 useState 或其他 React 钩子,并且你可以在 React 组件之外调用它,那么一个简单的函数是合适的?
    【解决方案5】:

    有一些差异和问题让我们使用 react 自定义钩子:

    1. 首先,如果你使用普通函数,每次重新渲染组件时,都会重新创建这个函数,导致性能不足。您可能认为可以通过使用useCallBack 来修复它,并且每次重新渲染时都不要创建新函数,但这不是我们要解决的主要问题。
    2. React 文档通过一个跟踪在线朋友的简短示例讨论了主要问题,即避免在不同的功能组件中复制粘贴相同的逻辑,这些功能组件也需要有状态。
    3. 如果我们在组件内部使用普通函数并使用useCallBack来避免每次都创建新函数,我们并没有解决问题,因为在每个组件中我们也应该复制这个逻辑,所以这没有解决问题。
    4. 另一种解决方案是在功能组件之外制作一个函数来处理这个逻辑,但是有一个大问题:在一个普通的功能在组件之外我们无法访问状态,因为正如我们所提到的,这个实现的逻辑是有状态的,我们只能访问 react 组件中的状态。

    那么这里的解决方案是什么?是的,自定义 React Hooks!

    1. 它是一个有状态函数,它使用其他 react 内置钩子(例如 useStateuseCallback 等),可以将您想要在一个地方收集的有状态逻辑包裹起来并避免在多个组件中复制和粘贴相同的逻辑。
    2. 通过这种方法,您可以将您的逻辑放在组件之外的另一个函数中,同时您可以从 react 的有状态功能中受益。

    我希望这个答案可以解决你的问题,解决你的歧义。

    【讨论】:

    • 在你的答案的第一部分(useCallback 的东西),看起来你混淆了回调函数(在渲染阶段创建)和常规函数与自定义钩子(两者都在外部创建反应生命周期)。那么最后的解决方案真的不符合你答案的前提!?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-20
    • 1970-01-01
    • 2020-01-23
    相关资源
    最近更新 更多