🏃

ReactComponentの中でdebounceを使いたくなったときメモ

2022/03/07に公開

ClassComponent時代は特に工夫の必要もなかったdebounce(とthrottle)ですが、FunctionComponentが基本となったhooks時代はそうもいきません。

というわけで毎回書いてるのでメモ。

import {useEffect, useMemo} from 'react';

import debounce from 'lodash.debounce';
import throttle from 'lodash.throttle';

export function useDebounce<T extends ReadonlyArray<unknown>, R>(func: (...arg: T) => R, wait: number, deps: ReadonlyArray<unknown> = []) {
  const dependencies = [...deps, wait];
  const memoized = useMemo(
    () => debounce(func, wait),
    dependencies,
  );
  useEffect(() => {
    return () => {
      memoized.cancel();
    };
  }, dependencies);
  return memoized;
}

export function useThrottle<T extends ReadonlyArray<unknown>, R>(func: (...arg: T) => R, wait: number, deps: ReadonlyArray<unknown> = []) {
  const dependencies = [...deps, wait];
  const memoized = useMemo(
    () => throttle(func, wait),
    dependencies,
  );
  useEffect(() => {
    return () => {
      memoized.cancel();
    };
  }, dependencies);
  return memoized;
}

はい。

たぶん色々とアプローチはあるとおもいます。一応他と比較検討してみたけど、これが一番シンプルだとおもいます。

しかし簡単に書きすぎていて、なんとなくrace conditionの可能性を秘めているような気もするんですが、strict modeで使い倒しても今のところ問題は出ていません。

安心ですね。
以上。

npmパッケージ化しようとおもったのですが、浦島太郎すぎて現代でTypeScriptのコードをパッケージングするやりかたのベストプラクティスがわかりませんでした。
誰か教えてください。

Discussion