likes
comments
collection
share

React必会:自定义Hook从入门到实战

作者站长头像
站长
· 阅读数 14

阅读时间约 5 分钟。


这段时间我们分享了一些 React 内置的钩子函数,如:useRef、useMemo、useReducer、useImperativeHandle 等。这些内置的钩子函数为我们的开发工作提供了极大的便利。除了 React 提供的内置 Hook 外,我们如何编写自己的钩子函数呢?

自定义 Hook 可以让我们在多个组件之间共享逻辑,提高代码的复用性和可维护性。要自定义一个钩子函数,我们应遵循以下规则:

  1. 自定义 Hook 必须以 use 开头。
  2. 自定义 Hook 必须是一个函数,函数内部可以使用 React 的 Hook。
  3. 自定义 Hook 必须返回数据或方法。

以上三条规则是我们必须要遵守的,在 React 官方文档中也都有提及。下面我们就通过一个简单的计数器示例来演示如何自定义一个通用的钩子函数。

1. 定义“计数器”钩子函数

要将计数器的通用逻辑提取到一个自定义 Hook 中,这个钩子函数应具有以下能力:

  1. 可以获取当前计数器的值;
  2. 能通过钩子函数给计数器增加值;
  3. 能通过钩子函数给计数器减少值。

根据这三条需求,我们可以实现下面的自定义 Hook:

import { useState } from 'react';

// 定义自定义 Hook 的返回值类型
type UseCounterReturnType = [count: number, increment: () => void, decrement: () => void];

// 定义自定义 Hook
export default function useCounter(initialCount: number = 0): UseCounterReturnType {
  // 使用 useState 来初始化 count 状态和 setCount 函数
  const [count, setCount] = useState(initialCount);

  // 定义 increment 函数,用于增加计数器的值
  const increment = () => {
    setCount(count + 1);
  };

  // 定义 decrement 函数,用于减少计数器的值
  const decrement = () => {
    setCount(count - 1);
  };

  // 返回 count、increment 和 decrement 函数作为自定义 Hook 的返回值
  return [count, increment, decrement];
}

我们通常会把自定义的 Hook 方法放到一个单独的文件中维护。上面的示例代码是由 TS 实现一个 useCounter 函数。还记得上面我们提到的三条规则吗?自定义 Hook 的函数名必须是 use 开头的。这个自定义函数中,我们定义了一个状态 count 用来记录计数器的值,同时定义了两个函数用来增加计数器的值和减少计数器的值。在函数最后,将他们放在一个数组中返回出去。

2. 使用“计数器”钩子函数

要使用上面的 useCounter 也非常简单,只需要像使用其他 Hook 一样调用即可。

import useCounter from './useCounter';

function MyComponent1(): JSX.Element {
  const [count, increment, decrement] = useCounter(10);

  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
    </div>
  );
}

上面的代码中,我们在调用 useCounter 时给计数器设置了一个默认值 10。当点击页面上的“Increment”按钮时,计数器加1;点击页面上的“Decrement”按钮时,计数器减 1。当前计数器的值渲染在 h1 标签中。

3. 应用场景

自定义 Hook 的应用场景非常广泛,下面总结了一些常见的应用场景:

  1. 处理数据逻辑

    在和后端接口交互时,我们可以借助自定义 Hook 将数据的获取、处理、缓存等抽象出来。比如,可以创建一个 useFetch Hook,用于从 API 接口中获取数据并缓存结果,以提高页面性能。

  2. 处理表单逻辑

    表单的验证、格式化等逻辑也可以抽象出来,比如可以创建一个 useForm 钩子函数来处理表单的数据和逻辑校验。

  3. 处理视图逻辑

    UI 上的一些操作,比如动画效果、手势操作、滚动处理的也可以抽象出来,比如创建一个 useSwipe 的钩子函数用于处理这些逻辑。

  4. 处理副作用

    我们常见的定时器、订阅事件等副作用也都可以用自定义的钩子函数来处理,比如可以创建一个 useInterval 用于处理定时器逻辑。

4. 总结

在创建和使用自定义 Hook 时,我们应该根据具体的业务或开发场景来选择合适的 Hook,灵活掌握自定义 Hook 的创建和使用能极大提高我们的开发效率,对提高代码可复用性和可维护性同样有很大的帮助。


本文首发微信公众号码上花甲,欢迎关注哦~