< Return home
David Ten Sing’s avatar
David Ten SingFront-End EngineerMelbourne, Australia
Learn how to create an input with debounced on change event handlerJun 1st 2023
How to debounce user search input correctly in react

The problem

Who doesn't love a searchbox where you get instant suggestions? aka auto-complete, aka auto-suggestion, aka instant results?

In my years as a frontend engineer, I have designed my fair share of autocomplete search boxes; whether it be with jQuery, Angular or React and every single time, I found myself having to do some sort of debounce and for some reason, I always can't quite figure out whether to debounce the input's change handler or the subsequent fetch call...

So here we are - this is a post for future me to remind me how to do this properly in React.

1. Leave the input as an uncontrolled element

If you want to keep the value of the input box in a state, then handle it in the debounced onChange handler but do not set the value props of the input on that state property.

If the input box needs a value when it first mounts, then use defaultValue props.

2. Create a memoized debounced version of your change handler

Do you normal thing and create an onChange handler. So you would be doing your state change or data fetching in that handler.

Now wrap your pass the onChange handler above into the debounce utility from lodash and wrap

Use the useMemo hook to return the debounced onChange handler.

const onChangeHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
  // do some side effects here
}

const debouncedSearch = useMemo(() => {
  return debounce(onChangeHandler, 500)
}, [])

// Use the debouncedSearch

<input name="search" placeholder="Search pokemons" onChange={debouncedSearch} />

3. Clean up the debounce on unmount

useEffect(() => {
  return () => {
    debouncedSearch.cancel()
  }
})

Here is a codepen of a working example - https://codesandbox.io/embed/debounced-search-eit7yr?fontsize=14&hidenavigation=1&theme=dark