Creating a Custom useDebounce Hook in React.js

Debouncing is a programming practice that limits the rate at which a function can fire. It ensures that a function is only executed after a certain amount of time has passed since its last invocation. The timer resets if the function is called again during this wait time.

A typical example of this in React is a search input:

  • Without debouncing: Function executes on every keystroke
  • With debouncing: Function executes only after the user stops typing for a set period (e.g., 500ms)

It's a common problem in app development so one of the utilities I used to solve this problem is creating a custom useDebounce hook.

useDebounce Hook

Here's my simple implementation of a clean and reusable debounce hook:

import { useState, useEffect } from 'react';

function useDebounce(value, delay = 500) {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    // Create a timeout to update the debounced value
    const timer = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    // Clean up the timeout if the value changes or the component unmounts
    return () => clearTimeout(timer);
  }, [value, delay]);

  return debouncedValue;
}

The hook works by: First, accepting an initial value and delay duration (defaulting to 500ms). Then, maintaining a debounced state that updates only after the specified delay. We use the useEffect to handle the timing logic. And then finally we need to properly clean up timeouts to prevent memory leaks

Working Example

Here's how I typically implement this hook in a search component:

function SearchComponent() {
  const [searchTerm, setSearchTerm] = useState('');
  const debouncedSearch = useDebounce(searchTerm, 500);

  useEffect(() => {
    // API call happens only after the debounced value changes
    if (debouncedSearch) {
      searchAPI(debouncedSearch);
    }
  }, [debouncedSearch]);

  return (
    <input
      type="text"
      value={searchTerm}
      onChange={(e) => setSearchTerm(e.target.value)}
      placeholder="Search..."
    />
  );
}

It's not just useful for search inputs, I use this hook for:

  • Search inputs
  • Window resize handlers
  • Save drafts
  • API calls on user input Plus whatever else I might not want to be called as fast as a person interacts with a page.

Creating a small library of hooks that you can drop into projects is useful for staying productive (and not reinventing the wheel every time you start a project).

Remember, while this implementation works well for most use cases, you might need to adjust the delay time based on your specific requirements. I typically use 500ms as a default, which can be modified depending on the use case and user experience needs.

Reactjs
Avatar for Niall Maher

Written by Niall Maher

Founder of Codú - The web developer community! I've worked in nearly every corner of technology businesses: Lead Developer, Software Architect, Product Manager, CTO, and now happily a Founder.

Loading

Fetching comments

Hey! 👋

Got something to say?

or to leave a comment.