Shadcn Hooks

useThrottleFn

A hook to throttle a function

Loading...

Installation

npx shadcn@latest add @hooks/use-throttle-fn
pnpm dlx shadcn@latest add @hooks/use-throttle-fn
yarn dlx shadcn@latest add @hooks/use-throttle-fn
bun x shadcn@latest add @hooks/use-throttle-fn

Copy and paste the following code into your project.

use-latest.ts
import { useRef } from 'react'
import { useIsomorphicLayoutEffect } from '@/registry/hooks/use-isomorphic-layout-effect'

export function useLatest<T>(value: T) {
  const ref = useRef(value)

  useIsomorphicLayoutEffect(() => {
    ref.current = value
  })

  return ref
}

use-unmount.ts
import { useEffect } from 'react'
import { useLatest } from '@/registry/hooks/use-latest'

export function useUnmount(fn: () => void) {
  const fnRef = useLatest(fn)

  useEffect(
    () => () => {
      fnRef.current()
    },
    [],
  )
}

use-throttle-fn.ts
import { throttle } from 'es-toolkit'
import { useMemo } from 'react'
import { useLatest } from '@/registry/hooks/use-latest'
import { useUnmount } from '@/registry/hooks/use-unmount'
import type { ThrottleOptions } from 'es-toolkit'

export type { ThrottleOptions }

export function useThrottleFn<Fn extends (...args: any[]) => any>(
  fn: Fn,
  throttleMs?: number,
  options?: ThrottleOptions,
) {
  const fnRef = useLatest(fn)

  const throttledFn = useMemo(
    () =>
      throttle(
        (...args: Parameters<Fn>) => fnRef.current(...args),
        throttleMs ?? 1000,
        options,
      ),
    [],
  )

  useUnmount(() => throttledFn.cancel())

  return {
    run: throttledFn,
    cancel: throttledFn.cancel,
    flush: throttledFn.flush,
  }
}

API

interface ThrottleOptions {
  /**
   * An optional AbortSignal to cancel the throttled function.
   */
  signal?: AbortSignal
  /**
   * An optional array specifying whether the function should be invoked on the leading edge, trailing edge, or both.
   * If `edges` includes "leading", the function will be invoked at the start of the delay period.
   * If `edges` includes "trailing", the function will be invoked at the end of the delay period.
   * If both "leading" and "trailing" are included, the function will be invoked at both the start and end of the delay period.
   * @default ["leading", "trailing"]
   */
  edges?: Array<'leading' | 'trailing'>
}

/**
 * A hook to throttle a function
 * @param fn - The function to throttle
 * @param throttleMs - The throttle time in milliseconds default to 1000
 * @param options - The options for the throttle function
 * @returns The throttled function
 */
function useThrottleFn<Fn extends (...args: any[]) => any>(
  fn: Fn,
  throttleMs?: number,
  options?: ThrottleOptions,
): {
  run: ThrottledFunction<(...args: Parameters<Fn>) => any>
  cancel: () => void
  flush: () => void
}

Credits

Last updated on