Hooks与普通函数的区别

Hooks与普通函数的区别

在这里的Hooks具体指的是自定义Hooks,自定义的Hooks与我们定义的普通函数类似,都可以封装逻辑,以实现逻辑的复用。Hooks实际上是一种特殊的函数,而由于Hooks的特殊实现,他们之间也存在着一定的区别。

描述

在我开始学习React Hooks的时候,我就比较疑惑这个问题。首先看一下官方文档,在自定义Hooks的部分说明了,构建自己的Hooks可以让您将组件逻辑提取到可重用的函数中。如果仅仅是这样的话,那么我们也完全可以使用普通的函数来实现逻辑的复用,而没必要去使用Hooks了。

当然在这里还是得先明确一点定义: 自定义Hooks就是很明确的定义了,其以use开头,内部可以调用其他的Hooks;在这里描述的的普通函数指的是我们平时写的抽离公共逻辑的函数,而不是在我们定义的普通函数中去调用其他Hooks这种方式。如果在普通函数中调用了其他Hooks,那么这个函数就不再是普通函数了,除了违反了Hooks的命名规则以外,那就完全是一个Hooks的定义了。

实际上,Coding比较重要的两个概念是逻辑与数据,文档中提到的将组件逻辑提取到可重用的函数中,重要的是逻辑这两个字,而在两个组件中使用相同的自定义Hooks是不会共享State的。如果我们直接编写一个普通的函数,那么对于其数据是在所有调用者中共享的,因为其只是一个模块,当然前提是我们不会去new出一个新对象来保存状态,在这里只讨论最plain的调用方式,因为Hooks也是直接以非常plain的方式进行调用的。

那么也就是说,如果我们使用Hooks的话,实际上由于可以调用useStateuseRefHooks,从而获取了对于这个Fiber的访问方法,那么也就相当于我们可以将状态或者说数据存放于当前节点当中,而不是类似于普通函数在全局中共享。当然如果需要全局共享状态的话,状态管理方案是更好的选择,而不是全局变量。

示例

举一个例子,对于数据请求,我们通常会封装一个request函数,假如我们需要对这个函数做一层缓存,那么就会有逻辑与数据的复用,在逻辑方面我们抽离出的方法差距不大,而对于数据缓存复用方面在这里通过普通函数与自定义Hooks的实现便是不同的。

普通函数

在普通函数当中,其就是一个模块,因此其数据是在所有调用者中共享的,因此我们可以通过一个Map来存储数据,这样就可以实现数据的复用。在这里需要注意的是,如果我们的url需要实现在不同组件调用返回的数据不同的话,例如可能会有根据当前页面的referer请求头来决定返回数据的需求,那么这种全局共享的数据就不适用了,就需要多添加一个参数来区分不同的数据,这样就会导致逻辑与数据的耦合,因此这种方式不是很好。当然这也是基于特定需求的,在这里只是举一个例子,毕竟实际上适合的才是最好的。

js 复制代码
const cache = new Map();
export fetch = (url) => {
  if (cache.has(url)) {
    return cache.get(url);
  }
  const promise = fetch(url);
  cache.set(url, promise);
  return promise;
}

自定义Hooks

在自定义Hooks当中,数据被锁定在了Fiber当中,也就是说数据的共享范围是在当前组件节点中,相对于全局状态共享来说粒度会更细一些。当然我们如果想直接在全局共享数据的话,这种方案就不合适了,可能还需要配合一个全局的状态管理才行。还是那句话,在这里只是举一个例子,毕竟实际上适合的才是最好的。

js 复制代码
const useRequest = (url) => {
    const map = useRef(new Map());
    if (map.current.has(url)) {
        return map.current.get(url);
    }
    const promise = fetch(url);
    map.current.set(url, promise);
    return promise;
}

总结

简单总结一下两者的区别:

  • 官方提供的Hooks只应该在React函数组件/自定义Hooks内调用,而不应该在普通函数调用。
  • 自定义Hooks能够调用诸如useStateuseRef等,普通函数则不能。由此可以通过内置的Hooks获得Fiber的访问方式,可以实现在组件级别存储数据的方案等。
  • 自定义Hooks需要以use开头,普通函数则没有这个限制。使用use开头并不是一个语法或者一个强制性的方案,更像是一个约定,就像是GET请求约定语义不携带Body一样,使用use开头的目的就是让React识别出来这是个Hooks,从而检查这些规则约束,通常也会使用ESlint配合eslint-plugin-react-hooks检查这些规则,从而提前避免错误的使用。

每日一题

arduino 复制代码
https://github.com/WindrunnerMax/EveryDay

参考

ruby 复制代码
https://www.zhihu.com/question/491311403
https://zh-hans.reactjs.org/docs/hooks-custom.html
https://stackoverflow.com/questions/60133412/react-custom-hooks-vs-normal-functions-what-is-the-difference
相关推荐
崔庆才丨静觅2 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60613 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了3 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅3 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅3 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅4 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment4 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅4 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊4 小时前
jwt介绍
前端
爱敲代码的小鱼4 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax