← All articles
Frontend1 min read

Debouncing and Throttling in Practice

Two techniques that look similar but solve different problems. When to reach for each, with copy-paste TypeScript implementations.

S

Swapnika Voora

Author

Rapid-fire events — keystrokes, scrolls, resizes — can overwhelm your handlers. Debouncing and throttling both tame them, but they behave differently and are easy to mix up.

The difference in one sentence

  • Debounce: wait until the events stop, then run once.
  • Throttle: run at most once per interval while events keep firing.

Debounce

Great for "wait until the user is done typing" — search-as-you-type, autosave, validating a form field.

debounce.ts
export function debounce<A extends unknown[]>(
  fn: (...args: A) => void,
  delay = 300,
) {
  let timer: ReturnType<typeof setTimeout> | undefined
 
  return (...args: A) => {
    clearTimeout(timer)
    timer = setTimeout(() => fn(...args), delay)
  }
}
 
// Usage
const search = debounce((q: string) => fetchResults(q), 250)
input.addEventListener("input", (e) => search(e.target.value))

Throttle

Great for "run periodically during a continuous action" — scroll position, mouse tracking, progress updates.

throttle.ts
export function throttle<A extends unknown[]>(
  fn: (...args: A) => void,
  interval = 200,
) {
  let last = 0
 
  return (...args: A) => {
    const now = Date.now()
    if (now - last >= interval) {
      last = now
      fn(...args)
    }
  }
}

Using it in React

Wrap the debounced function in a ref so it survives re-renders:

use-debounced-value.ts
import { useEffect, useState } from "react"
 
export function useDebouncedValue<T>(value: T, delay = 300) {
  const [debounced, setDebounced] = useState(value)
 
  useEffect(() => {
    const id = setTimeout(() => setDebounced(value), delay)
    return () => clearTimeout(id)
  }, [value, delay])
 
  return debounced
}

Which one do I want?

Ask: do I care about the final state, or a steady sample of intermediate states? If the final state matters, debounce. If you want smooth periodic updates, throttle. Get this right and janky UIs become buttery smooth.

#javascript#typescript#performance#ux

More in Frontend