DEV Community

Matan Shaviro
Matan Shaviro

Posted on • Edited on

Implementing a Debounce Hook in React with Typescript

When building interactive applications, we often need to control how frequently a function executes, especially in cases where an action (like a search or API call) is triggered each time a user types into an input. Here, we’ll create a custom useDebounce hook that will help manage these frequent calls by delaying the response to user input.

In this post, we’ll walk through a basic React app that includes a useDebounce hook to debounce a search input. This example app includes:

  • App component: handles user input and displays it.
  • useDebounce hook: implements the debounce logic.
function App() {
  const [search, setSearch] = React.useState('')
  const debouncedSearch = useDebounce(search, 200)

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setSearch(e.target.value)
  }

  return (
    <div className="App">
      <input value={debouncedSearch} onChange={handleChange} />
    </div>
  )
}

export default App
Enter fullscreen mode Exit fullscreen mode

Explanation:

  1. State for Search Term: We define a state variable search using React.useState to keep track of the user's input.

  2. Debounced Value: We pass the search term and a delay (200 milliseconds) to the useDebounce hook. The useDebounce hook returns a debouncedSearch value, which only updates if the user stops typing for 200 milliseconds.

  3. Handling Input Changes: In the handleChange function, we update the search state as the user types in the input field.

  4. Render the Input: The field is controlled by debouncedSearch. When a user types, the handleChange function captures each keystroke, but the input reflects changes with a 200ms delay, providing a smoother experience.

Now, let’s break down the useDebounce hook that manages the debounce effect:

export const useDebounce = <T>(value: T, delay = 500) => {
  const [debouncedValue, setDebouncedValue] = useState(value)

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

    return () => clearTimeout(timeout)
  }, [value, delay])

  return debouncedValue
}
Enter fullscreen mode Exit fullscreen mode

Explanation:

  1. State for Debounced Value: We create a debouncedValue state to store the delayed value. This state only updates after the delay.

  2. useEffect Dependency: Inside the useEffect hook, we set a timeout to update debouncedValue after the specified delay. This ensures that if a new value is provided before the delay completes, the previous timeout is cleared, and a new one is set.

  3. Clear Timeout on Cleanup: The return statement inside useEffect defines a cleanup function. When value or delay changes, clearTimeout is called to cancel the previous timer. This way, the timeout is reset each time the user types, so the debouncedValue only updates if the user stops typing.

  4. Return the Debounced Value: Finally, useDebounce returns the debouncedValue. This value is stable (won’t change immediately) and reflects the input with a delay, reducing the frequency of updates in the App component.

Wrapping Up

With the useDebounce hook, we improve the performance and responsiveness of our app by ensuring updates only happen after the user stops typing. This simple hook can be adapted to any type of value, making it a versatile addition to your React projects.

Top comments (0)