Debounce

Debounce
debounce.js
const debounce = (callback, wait) => {
  let timeoutId = null;
  
  return (...args) => {
	window.clearTimeout(timeoutId);
	
	timeoutId = window.setTimeout(() => {
	  callback.apply(null, args);
	}, wait);
  };
}

Why

There are many events in JS that trigger super quickly.

When you scroll the page, or resize the window, or move your mouse, the browser captures dozens and dozens of events per second.

Usually, you don't need to capture every single intermediate step; you're only interested in capturing the end state (when the user finishes scrolling, or finishes resizing the window).

Debouncing is a strategy that lets us improve performance by waiting until a certain amount of time has passed before triggering an event. When the user stops triggering the event, our code will run.

In some cases, this isn't necessary. But, if any network requests are involved, or if the DOM changes (eg. re-rendering a component), this technique can drastically improve the smoothness of your application.

Usage

const handleMouseMove = debounce((ev) => {
  // Do stuff with the event!
}, 250);

window.addEventListener('mousemove', handleMouseMove);

In this example, nothing will happen until the user starts moving the mouse, and then stops moving it for at least 250ms.

Note that this example is focused on vanilla JS. If you're using React, you'll want to wrap your handler in useCallback, so that it doesn't get re-generated on every render.

Here's an example that debounces the capturing of the mouse's X coordinate:

function App() {
  const [mouseX, setMouseX] = React.useState(null);
  const handleMouseMove = React.useCallback(
	debounce((ev) => {
	  setMouseX(ev.clientX);
	}, 250),
	[]
  );
  return (
	<div onMouseMove={handleMouseMove}>
		Mouse position: {mouseX}
	</div>
  );
}