反应自定义钩子与普通函数,有什么区别



我正在尝试围绕自定义钩子进行思考。 我理解普通钩子很好,但我的问题是,在编写自定义钩子时,它和普通函数有什么区别? 我的意思是为什么不称它为普通函数而不是称其为类似 use*

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

React Hooks 是具有 react 功能的 JS 函数,这意味着您可以添加一些逻辑,您也可以将其添加到普通的 JS 函数中,但您也可以使用本机钩子,如 useState、useEffect 等,来启动该逻辑,添加它的状态,或添加它的副作用, 记忆或更多。 所以我相信钩子是一件非常好的事情,可以以隔离的方式管理组件的逻辑。

所以,你可以有一个foo.component.js(UI),一个useFoo.js(logic),其中useFoo将包含许多js函数和一个钩子来管理该函数并返回它应该的内容。

这是一个关于反应钩子的惊人视频,完全推荐

https://youtu.be/J-g9ZJha8FE

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

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

那么这里的解决方案是什么? 是的,自定义反应钩子!

  1. 它是一个有状态函数,使用其他反应内置钩子(例如useStateuseCallback等)这可以环绕您希望在一个位置收集的有状态逻辑,并避免在多个组件中复制和粘贴相同的逻辑。
  2. 使用这种方法,您可以将逻辑放在组件之外的另一个函数中,同时获得 react 的有状态功能的好处。

我希望这个答案可以解决你的问题,解决你的模棱两可。

来自 React 文档:

自定义 Hook 是一个 JavaScript 函数,其名称以 "use" 开头,可以调用其他 Hook。[...]它的名称应该始终以"use"开头,以便您可以一目了然地判断出 Hooks 的规则适用于它。

那么为什么要用特殊的"use"命名前缀定义自定义 Hook 呢?

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

2.) 您可以获得检查和执行这些规则的工具支持。例如,eslint-plugin-react-hooks使用一种启发式方法,该启发式假设一个以"use"前缀开头的函数,并在它是 Hook 之后使用大写字母。

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

1) 钩子应该只从 React 代码调用,而不是从常规 JS 函数调用。因此,Hooks 的范围仅限于 React 代码世界,并且有更多的能力来做很多事情来处理 React 代码。而不是JS,常规函数可以跨应用程序使用,但作为反应代码指南,代码与反应语法更加一致。

2)在基于类的组件中,钩子不起作用,但常规函数会。

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

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

你可以随心所欲地命名你的钩子函数,但正如我提到的,如果在渲染方法之外使用,你会得到来自 React 的警告。

你可以随便称呼它,它仍然可以正常工作。唯一的优点是,如果你使用 "useName" 约定,React 会检查它是否正确遵循钩子规则的错误。它只是使您的任务稍微容易一些。

正如其他用户所说,自定义钩子或钩子,一般来说,用于我们必须做任何与反应组件相关的事情,而其他 util 函数不绑定到反应状态并且不起作用是反应状态逻辑到位的区域。

自定义钩子的一个例子是useCustomNavigation,它可以是一个导航器功能的列表,如navigateToHome,navigateToCheckout等。因此,当您从代码的不同部分路由到主页时,我们只使用这个钩子。此外,任何逻辑/功能(如分析和副作用)都可能是导航到主页功能的一部分。

Util 函数的一个例子可以是像大写这样的东西,它不必与反应或反应组件做任何事情。您不能创建名为 navigator 的 util 函数并添加 useNavigation。

在我看来,自定义钩子有其特定的用途,并具有自己的特征和方法。 我的意思是,在某些情况下,我们希望创建自定义钩子而不是函数。

例如,如果您需要在 Localstorage 中存储一些数据,则需要为其创建自定义钩子并将其称为"useLocalStorage",如果您想创建一个组件,例如页面表单,则需要编写一个函数组件。

不同之处在于我们的钩子不是一个组件,在我们的 UI 上不显示任何内容。 这只是一个逻辑操作。

我认为它们与上面的"逻辑"示例不同,原因是我们的自定义钩子在允许使用其他自定义钩子相关钩子的方式上是独一无二的。例如,只能在自定义钩子中工作的"useDebugValue"。

对我来说奇怪的是 React 将函数与自定义钩子区分开来的方式,我认为这是造成混淆的主要原因。 它"检查"您的函数名称,如果它以"use"开头,那么它是一个自定义钩子。我认为更好的选择是将"const"声明更改为"hook"声明或为其提供唯一类型。

TL;DR,自定义钩子是逻辑,将允许使用像"useDebugValue"这样的钩子,我们的函数大多与UI相关。

自定义钩子是一个调用其他 React 钩子的函数,因此必须在 React 组件的上下文中并根据钩子规则调用。 命名约定提醒您这一点。

钩子中的代码就像它在调用者中内联一样运行,但是将其放在钩子函数中可以重用并使用明确定义的输入和输出封装。

相关内容

  • 没有找到相关文章

最新更新