logoahooks dive
Effect

useDebounceFn

用于管理防抖函数的 Hook

用法

Clicked count: 0

源码

useDebounceFn.ts
import { debounce } from '../utils/lodash-polyfill';
import { useMemo } from 'react';
import type { DebounceOptions } from '../useDebounce/debounceOptions';
import useLatest from '../useLatest';
import useUnmount from '../useUnmount';
import { isFunction } from '../utils';
import isDev from '../utils/isDev';

type noop = (...args: any[]) => any;

function useDebounceFn<T extends noop>(fn: T, options?: DebounceOptions) {
  if (isDev) {
    if (!isFunction(fn)) {
      console.error(`useDebounceFn expected parameter is a function, got ${typeof fn}`);
    }
  }

  const fnRef = useLatest(fn);

  const wait = options?.wait ?? 1000;

  const debounced = useMemo(
    () =>
      debounce(
        (...args: Parameters<T>): ReturnType<T> => {
          return fnRef.current(...args);
        },
        wait,
        options,
      ),
    [],
  );

  useUnmount(() => {
    debounced.cancel();
  });

  return {
    run: debounced,
    cancel: debounced.cancel,
    flush: debounced.flush,
  };
}

export default useDebounceFn;

解读

关于 useLatestuseUnmount,可以查看对应文档:useLatestuseUnmount

function useDebounceFn<T extends noop>(fn: T, options?: DebounceOptions) {
  // 1. 首先,使用 useLatest 来记录函数的最新值。
  const fnRef = useLatest(fn);

  // 2. 然后,使用 options 中的 wait 属性来设置防抖时间,默认值为 1000ms。
  const wait = options?.wait ?? 1000;

  // 3. 接着,使用 useMemo 来缓存防抖后的函数。防抖后的函数内部会调用 fnRef 对象的值,并返回函数的执行结果。
  const debounced = useMemo(
    () =>
      // 使用 lodash 的 debounce 函数实现防抖函数,参数配置也完全与 lodash 的 debounce 函数一致。
      debounce(
        (...args: Parameters<T>): ReturnType<T> => {
          return fnRef.current(...args);
        },
        wait,
        options,
      ),
    [],
  );

  // 4. 然后,使用 useUnmount 来卸载防抖后的函数。
  useUnmount(() => {
    debounced.cancel();
  });

  // 5. 最后,返回防抖后的函数,包括 run、cancel、flush 三个方法。
  return {
    run: debounced,
    cancel: debounced.cancel,
    flush: debounced.flush,
  };
}

本质上就是利用 debounce 来延时更新 state 的值,完全可以利用 setTimeout 来实现一个简易的版本。

Value:

DebouncedValue(延时 500ms 后更新):

Last updated on

On this page