React Debounce Hook

2024-05-18
By: O Wolfson

Debouncing is a programming practice used to ensure that time-consuming tasks do not fire so often, optimizing performance and improving user experience. In the context of web development, it's particularly useful for handling events like keystrokes, button clicks, and window resizing.

Why We Need Debounce

Imagine you have a search input field that queries a database with each keystroke. Without debouncing, every character typed would send a request, overwhelming your server and leading to performance issues. Debouncing consolidates multiple actions into a single one after a specified delay, ensuring efficiency and reducing load.

Check out a simple example of debouncing in action deployed at https://debounce-hook.vercel.app/.

Examples of Debounce Usage

  1. Search Inputs: Preventing multiple API calls as the user types.
  2. Window Resize Events: Avoiding performance bottlenecks when adjusting layouts.
  3. Button Clicks: Preventing accidental multiple submissions.

Understanding React Hooks

React hooks are functions that let you use state and other React features without writing a class. They simplify code and make components more readable. In this article, we’ll create a custom hook called useDebounce to demonstrate debouncing in a React app.

Creating the useDebounce Hook

The useDebounce hook will take a value and a delay as arguments, returning the debounced value. Here’s the code:

typescript
import { useState, useEffect } from "react";

export const useDebounce = (value: any, delay: number) => {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => {
      clearTimeout(handler);
    };
  }, [value, delay]);

  return debouncedValue;
};

Using the useDebounce Hook in a Next.js App

To demonstrate the debounce functionality, we'll create a simple component that shows the difference between debounced and non-debounced values. Here's how to set it up in a Next.js app:

  1. Create the Hook File: Save the useDebounce hook in my-next-app/app/hooks/useDebounce.ts.

  2. Create the Demo Page: Save the following component in my-next-app/app/page.tsx.

typescript
"use client";
import { useState } from "react";
import { useDebounce } from "./hooks/useDebounce";

const DebounceDemo = () => {
  const [inputValue, setInputValue] = useState("");
  const debouncedValue = useDebounce(inputValue, 500);

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setInputValue(event.target.value);
  };

  return (
    <div className="flex flex-col gap-4 p-8">
      <h2 className="font-bold text-2xl">Debounce Hook Demo</h2>
      <input
        type="text"
        value={inputValue}
        onChange={handleChange}
        placeholder="Type something..."
        className="p-2 border border-gray-300 rounded"
      />
      <div>
        <h4 className="font-bold text-xl">Output With Debounce</h4>
        <p className="text-sm pb-2">Half a second delay</p>
        <p className="text-2xl">
          <span className="font-semibold">{debouncedValue}</span>
        </p>
      </div>
      <div>
        <h4 className="font-bold text-xl">Output Without Debounce</h4>
        <p className="text-sm pb-2">No delay</p>
        <p className="text-2xl">
          <span className="font-semibold">{inputValue}</span>
        </p>
      </div>
    </div>
  );
};

export default DebounceDemo;

Conclusion

By using the useDebounce hook, you can improve the performance and user experience of your React applications. This custom hook is simple yet powerful, demonstrating how React hooks can be used to encapsulate and reuse logic across your components.

Debouncing is a crucial technique for optimizing event-driven applications, and creating a custom hook in React makes it even more convenient to implement.