Skip to content

Latest commit

 

History

History
109 lines (74 loc) · 4.27 KB

使用 Typescript 编写自定义 React useDebounce Hook.md

File metadata and controls

109 lines (74 loc) · 4.27 KB

使用 TypeScript 编写自定义 React useDebounce Hook

React Hooks 中,我们介绍了如何使用,以及它的一些常用内置的 React Hooks 钩子,并在最后一节中,我们了解如何自定义钩子。这使我们可以将组件逻辑抽象为可重用的函数。

在本文中,我们将继续使用 TypeScript 编写一个自定义 useDebounce 钩子!

关于防抖,你可以看看我之前写的两篇文章:

我们的自定义钩子应该如何工作?

我们可以通过多种方式编写钩子,但让它的用法看起来与 setState 钩子的用法相对类似:

const [value, setValue] = useState<string>('')

不同之处在于,我们希望:

  • 指定防抖时间
  • 同时获取当前值和防抖值

所以它应该看起来像这样:

const [debouncedValue, value, setValue] = useDebounce<string>('', 1000)

然后,我们可以使用 useEffect 钩子根据 debouncedValue 更改采取一些操作:

const [debouncedValue, value, setValue] = useDebounce<string>('', 1000)

useEffect(() => {
  // do something
}, [debouncedValue])

useDebounce 类型

首先,让我们创建 useDebounce 函数,并确保正确定义了其参数和返回类型。我们希望确保钩子采用泛型,为 initialValue(初始值)、debouncedValue(防抖值)和 value(当前/最新值)提供类型。

我们的两个参数 initialValuetime 分别是泛型类型和数字类型。

最后,我们的函数将返回三个元素组成的数组。第一个元素 debouncedValue 是泛型类型,第二个元素 value 也将是泛型类型,最后一个元素将是我们的设置的 React.Dispatch 类型。

function useDebounce<T>(
  initialValue: T,
  time: number
): [T, T, React.Dispatch<T>] {}

编写一个没有防抖的版本

我们的钩子需要保持两种状态:最新/当前值和防抖值。我们将使用 useState 钩子来维护这些状态。为了立即制作一个非常简单的版本,我们将使用 useEffect 钩子来确定最新值的更改时间,并立即更改防抖值。将来,我们将处理此过程的延迟问题。

import { useState, useEffect } from 'react'

function useDebounce<T>(
  initialValue: T,
  time: number
): [T, T, React.Dispatch<T>] {
  const [value, setValue] = useState<T>(initialValue)
  const [debouncedValue, setDebouncedValue] = useState<T>(initialValue)

  useEffect(() => {
    setDebouncedValue(value)
  }, [value])

  return [debouncedValue, value, setValue]
}

添加防抖函数

接下来可以添加抖动函数了。为此,我们可以在 useEffect 中使用 setTimeout。这里的关键是从 useEffect 返回一个函数来取消超时。这个函数本质上是类组件 componentWillUnmount 钩子的等效函数!

import React, { useState, useEffect } from 'react'

function useDebounce<T>(
  initialValue: T,
  time: number
): [T, T, React.Dispatch<T>] {
  const [value, setValue] = useState<T>(initialValue)
  const [debouncedValue, setDebouncedValue] = useState<T>(initialValue)

  useEffect(() => {
    const debounce = setTimeout(() => {
      setDebouncedValue(value)
    }, time)
    return () => clearTimeout(debounce)
  }, [value, time])

  return [debouncedValue, value, setValue]
}

演示地址

最后

对于 React 的 TypeScript 实践,有一个不错的项目 React TypeScript Cheatsheets,它为经验丰富的 React 开发人员提供 TypeScript 入门的备忘单。

另外,如果你看到英文头疼,有一篇不错的文章 🔖TypeScript 备忘录:如何在 React 中完美运用?,其中作者的一些实际经验和这份备忘单,值得一读。