如何写自定义 React Hook?

简介: 前端西瓜哥

大家好,我是在学习 React 的前端西瓜哥。

我们在写 React 函数组件时,如果想要复用组件的部分逻辑,可以考虑写自定义 Hook。本文会教大家如何写自定义 React Hook。

Hook 的规则

在此之前,我们先了解一下 Hook 的使用规则。

首先 Hook 只能在函数组件的顶层使用,不能在循环、条件、嵌套函数中执行。

这和 React Hook 的实现原理有关。当第一次执行函数组件时,React 会分配一个对象,然后一个个调用 Hook 时,将传入的参数或得到的结果依次放入到有序的表中缓存起来,然后保存在该对象中。

之后再次执行函数组件时,必须要保证这些 Hook 的执行顺序相同,才能做依赖项的对比,以及和前一次渲染的状态的对比等对比逻辑。

如果能 hook 可以出现循环、条件、嵌套函数中,就不能保证 Hook 执行顺序不变。

此外Hook 只能在函数组件内工作,不要在非组件函数中使用 Hook

如果你在普通函数内使用了 Hook,React 会报错。

当然如果是自定义 Hook(一个使用了 React 内置 Hook 的普通函数),然后放到函数组件内,那也是合法的。

为防止开发者不小心写岔,React 官方还写了一个名为 eslint-plugin-react-hooks 的 ESLint 插件,用于检测不合法的 Hook 调用位置,实在是太贴心了。强烈建议使用。

写自定义 Hook

自定义 Hook,就是使用了内置 Hook 的普通函数。它是对函数组件可复用的部分逻辑的做了一层封装,然后再被函数组件使用。

自定义的 Hook 必须使用 use 开头。因为 React 的官方 ESLint 插件认为 use 开头是自定义 Hook。

如果你不用 use 开头,ESLint 插件就会认为这是一个普通函数,调用时不符合 Hook 规则时不会报错,你就可能写出有问题的代码。

另外,自定义 Hook 下使用的 Hook,也必须位于顶层,这也是为了保证 hook 的顺序多次执行能保持一致。

下面我们来写几个常用的自定义 Hook。

useMount / useUnmount

我们希望实现类似类函数 componentDidMount 的效果。

const useMount = fn => {
  useEffect(() => {
    fn();
  }, []);
}

使用方式:

function App = () => {  
  // 自定义 Hook
  useEffect(() => {
    console.log('挂载');
  });
  // 原来的写法
  useEffect(() => {
    console.log('挂载');
  }, []);
}

相比原来的 useEffect 的实现,做了封装后的 useMount 更语义化一些。外也不需要写多余的依赖项,并将组件销毁的回调函数也隔离出去了。

类似类函数 componentWillUnmount 的 useUnmount Hook 实现如下:

const useUnmount = fn => {
  useEffect(() => fn, []);
}
// 用法
useUnmount(() => {
  console.log('销毁');
})

useUpdateEffect

下面我们再实现一个 useEffect 的剔除掉挂载那一次的版本,对标类函数的 componentDidUpdate。

const useUpdateEffect = (fn, deps) => {
  const isMount = useRef(true);
  useEffect(() => {
    if (isMount.current) {
      isMount.current = false;
      return;
    }
    return fn();
  }, deps);
}
// 用法
useUpdateEffect(() => {
  console.log('更新');
})

思路其实很简单,就是多使用一个默认值为 true 的布尔值变量。我们用它来记录当前是否为第一次执行,如果是,就不执行传入的函数,然后将布尔值设置为 false。

false 代表之后都是第二次第三次的执行,每次都执行传入的函数。

这里我们没有用 useState,因为通过 setState 方法会重新渲染组件。所以我们使用了 useRef,修改它的值不会触发组件的更新。

结尾

自定义 Hook,是一种比组件更小粒度的可复用逻辑组织方式,这也是 React 函数组件带给我们最大的惊喜。为此,我们有必要学习好自定义 Hook。

我是前端西瓜哥,欢迎关注我。

相关文章
|
1月前
|
设计模式 存储 前端开发
React开发设计模式及原则概念问题之自定义Hooks的作用是什么,自定义Hooks设计时要遵循什么原则呢
React开发设计模式及原则概念问题之自定义Hooks的作用是什么,自定义Hooks设计时要遵循什么原则呢
|
18天前
|
前端开发 Python
React技术栈-React路由插件之自定义组件标签
关于React技术栈中React路由插件自定义组件标签的教程。
37 4
React技术栈-React路由插件之自定义组件标签
|
1月前
|
前端开发 JavaScript
|
20天前
|
前端开发
React 中的 Hook 概念
【8月更文挑战第31天】
20 0
|
2月前
|
前端开发 JavaScript 数据格式
react18【系列实用教程】Hooks (useState,useReducer,useRef,useEffect,useContext,useMemo,useCallback,自定义 Hook )
react18【系列实用教程】Hooks (useState,useReducer,useRef,useEffect,useContext,useMemo,useCallback,自定义 Hook )
56 1
|
2月前
|
前端开发
React useImperativeHandle Hook
【7月更文挑战第1天】React useImperativeHandle Hook
19 3
|
2月前
|
前端开发
Vue3 【仿 react 的 hook】封装 useTitle
Vue3 【仿 react 的 hook】封装 useTitle
28 0
|
2月前
|
前端开发 API
Vue3 【仿 react 的 hook】封装 useLocation
Vue3 【仿 react 的 hook】封装 useLocation
24 0
|
3月前
|
JSON 弹性计算 前端开发
函数计算产品使用问题之遇到在自定义运行时部署React项目时遇到样式无法正常加载。一般是什么导致的
函数计算产品作为一种事件驱动的全托管计算服务,让用户能够专注于业务逻辑的编写,而无需关心底层服务器的管理与运维。你可以有效地利用函数计算产品来支撑各类应用场景,从简单的数据处理到复杂的业务逻辑,实现快速、高效、低成本的云上部署与运维。以下是一些关于使用函数计算产品的合集和要点,帮助你更好地理解和应用这一服务。
|
4月前
|
前端开发 数据可视化 API
前端react 18.2整合ckeditor富文本编辑器——配置插件、自定义toolbar工具栏(二)
前端react 18.2整合ckeditor富文本编辑器——配置插件、自定义toolbar工具栏
299 0
前端react 18.2整合ckeditor富文本编辑器——配置插件、自定义toolbar工具栏(二)

热门文章

最新文章