128. [ソースコードの読み取り] ahooks -- useDebounce、useDebounceFn、useCreation、useUnmount、usePersistFn

デバウンスを使用する

import {
    
     useState, useEffect } from 'react';
import useDebounceFn from '../useDebounceFn';
import {
    
     DebounceOptions } from './debounceOptions';

/**
 * @description: 用来处理防抖值的 Hook。
 * @param {T} value 需要防抖的值
 * @param {DebounceOptions} options {wait:	超时时间,单位为毫秒;leading:	是否在上升沿触发副作用函数; trailing:	是否在下降沿触发副作用函数;}
 * @return {*}
 */
function useDebounce<T>(value: T, options?: DebounceOptions) {
    
    
  const [debounced, setDebounced] = useState(value);

  const {
    
     run } = useDebounceFn(() => {
    
    
    setDebounced(value);
  }, options);

  useEffect(() => {
    
    
    run();
  }, [value]);

  return debounced;
}

export default useDebounce;

// DebounceOptions
export interface DebounceOptions {
    
    
  wait?: number;
  leading?: boolean;
  trailing?: boolean;
}

デバウンスFnを使用する

lodash.debounce

debounced 関数には、遅延した関数呼び出しをキャンセルする cancel メソッドと、すぐに呼び出す flash メソッドが用意されています。

import debounce from 'lodash.debounce';
import {
    
     useRef } from 'react';
import useCreation from '../useCreation';
import {
    
     DebounceOptions } from '../useDebounce/debounceOptions';
import useUnmount from '../useUnmount';

type Fn = (...args: any) => any;

/**
 * @description: 用来处理防抖函数的 Hook。
 * @param {T} fn 需要防抖执行的函数
 * @param {DebounceOptions} options {wait:	超时时间,单位为毫秒;leading:	是否在上升沿触发副作用函数;trailing	:是否在下降沿触发副作用函数;}
 * @return {*}{run:	触发执行 fn,函数参数将会传递给 fn;cancel:	取消当前防抖; flush:	当前防抖立即调用}
 */
function useDebounceFn<T extends Fn>(fn: T, options?: DebounceOptions) {
    
    
  const fnRef = useRef<T>(fn);
  fnRef.current = fn;

  const wait = options?.wait ?? 1000;

  /**
   * @description: 通过useCreation 执行debounce
   * @param {*}
   * @return {*}
   */
  const debounced = useCreation(
    () =>
      debounce<T>(
        ((...args: any[]) => {
    
    
          return fnRef.current(...args);
        }) as T,
        wait,
        options,
      ),
    [],
  );

  // 卸载时取消延迟的函数调用
  useUnmount(() => {
    
    
    debounced.cancel();
  });

  return {
    
    
    run: (debounced as unknown) as T,
    cancel: debounced.cancel,
    flush: debounced.flush,
  };
}

export default useDebounceFn;

使用作成

import {
    
     useRef } from 'react';

/**
 * @description: useCreation 是 useMemo 或 useRef 的替代品。因为 useMemo 不能保证被 memo 的值一定不会被重计算,而 useCreation 可以保证这一点。
 * @param {function} factory 用来创建所需对象的函数
 * @param {any} deps 传入依赖变化的对象
 * @return {*}
 */
export default function useCreation<T>(factory: () => T, deps: any[]) {
    
    
  // 通过useRef设置一个标记initialized
  const {
    
     current } = useRef({
    
    
    deps,
    obj: undefined as undefined | T,
    initialized: false,
  });

  // 判断第一次 或者依赖变化的对象发生改变时 触发factory
  if (current.initialized === false || !depsAreSame(current.deps, deps)) {
    
    
    current.deps = deps;
    current.obj = factory();
    current.initialized = true;
  }
  return current.obj as T;
}

/**
 * @description: 判断依赖性deps是否发生改变
 * @param {any} oldDeps
 * @param {any} deps
 * @return {*}
 */
function depsAreSame(oldDeps: any[], deps: any[]): boolean {
    
    
  if (oldDeps === deps) return true;
  for (const i in oldDeps) {
    
    
    if (oldDeps[i] !== deps[i]) return false;
  }
  return true;
}

使用アンマウント

import {
    
     useEffect } from 'react';
import usePersistFn from '../usePersistFn';
import {
    
     isFunction } from '../utils';

/**
 * @description: 只在组件 unmount 时执行的 hook。
 * @param {any} fn
 * @return {*}
 */
const useUnmount = (fn: any) => {
    
    
  const fnPersist = usePersistFn(fn);

  useEffect(
    () => () => {
    
    
      if (isFunction(fnPersist)) {
    
    
        fnPersist();
      }
    },
    [fnPersist],
  );
};

export default useUnmount;

// utils isFunctin
/**
 * @description: 判断是否是一个function
 * @param {any} obj
 * @return {boolean}
 */
export function isFunction(obj: any): obj is Function {
    
    
  return typeof obj === 'function';
}

usePersistFn

/**
 * @description: 持久化 function 的 Hook。
 * @param {T} fn 需要持久化的函数
 * @return {fn} 引用地址永远不会变化的 fn
 */
function usePersistFn<T extends noop>(fn: T) {
    
    
  const fnRef = useRef<T>(fn);
  fnRef.current = fn;

  const persistFn = useRef<T>();
  if (!persistFn.current) {
    
    
    persistFn.current = function (...args) {
    
    
      return fnRef.current!.apply(this, args);
    } as T;
  }

  return persistFn.current!;
}

export default usePersistFn;

おすすめ

転載: blog.csdn.net/zm06201118/article/details/115007695