Debounce Function Issue in useEffect

Let's say we want to make a fetch API call each time the query parameter changes. We're also going to add a debouncer because these changes can happen quickly. Here’s what our starting code looks like:

// doesn't work
useEffect(() => {
  debounce(() => {
    fetchData(queryParamValue)
  }, 500)
}, [queryParamValue])

The problem here is that the debouncer doesn't perform any meaningful action; it merely delays each useEffect execution by 500 ms.

To address this issue, we need to refactor the code and utilize theuseCallback React hook:

// step 1: refactoring
useEffect(() => {
    onQueryHandler()
}, [queryParamValue])

const onQueryHandler = useCallback(
   debounce(() => {
    fetchData(queryParamValue)
  }, 500),
[]);

The debouncer is working now, and we are using useCallback without any dependencies. This means we won't get the latest value of queryParamValue. This is fine if we don't need to send it's value to the backend with the fetchData function. However, in our case, we do need to send it to the server.

If we add queryParamValue to the dependencies of useCallback, we will face the same issue again. Therefore, we will leave the dependencies empty as it is.

We can pass the latest queryParamValue as a parameter in onQueryHandler within useEffect:

// step 2: passing value as an argument
useEffect(() => {
    onQueryHandler(queryParamValue)
}, [queryParamValue])

const onQueryHandler = useCallback(
  debounce(queryParamValue => {
    fetchData(queryParamValue)
  }, 500),
[]);

Now, our debouncer function is working perfectly!