Delay a Function Call using React Custom Hook: Debounce
Tags: react, tutorial, javascript
Published: 2023-02-07 02:53:36

##What is Debouncing? 

Debouncing is a technique or pattern in programming that limits the number of times a function can be executed within a specific time interval.

##Why is Debouncing Important?

Debouncing can prevent an application from becoming slow or unresponsive. It is used to improve the performance and responsiveness of applications. 

In React, one place where we may use debouncing is with text input fields in order to prevent the execution of an expensive function, such as a data fetch, until the user has finished typing.

For example, let's say we are programming a notes app with a text input field. After the user finishes typing, we would like the app to automatically save the user input text and commit these changes to the server. Without debouncing, a server request would be made with each letter typed. In that case, a small paragraph could trigger a few hundred fetch requests! As you could imagine, this can quickly slow the app's performance and, because many API's limit the number of requests made in a given time period, this may reach the request limit and prevent the app from properly communicating with the server. Not good! 

Using debouncing, the fetch request can be delayed until X number of seconds _after_ the user has finished typing. Even delaying the function call by just 1 to 2 seconds can greatly improve the performance of the application and lower the number of requests made to and from the API server! 

One common way to implement debouncing in our code is to create a custom hook to handle this functionality.

##What is a Custom Hook?

Custom hooks are a feature in React that allow you to extract code and reuse it across multiple components. With custom hooks, you can create the logic for debouncing a function in a hook and make it reusable and easy to use across your application. This helps limit repeated code and keep your code ["DRY"](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself). 

**Note**: There are several ways to debounce a function in React. Creating a custom hook is just one way to do it, but this code can also be altered and written directly in the component where your function exists.

##Creating a Custom Hook for Debounce

A common approach to debouncing is to use the `setTimeout()` and `clearTimeout()` methods. These methods set a timer which executes a function once the timer expires. Read the official documentation for these methods [here](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout). 

To create a custom hook for debouncing, we will write a function that returns a debounced value using the `setTimeout()` and `clearTimeut()` methods. The hook will take two arguments: the value to be debounced, and the debouncing delay (a number in milliseconds).

Here is the code for our custom hook:

```javascript
import { useState, useEffect } from "react";
const useDebounce = (value, delay) => {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const timeoutID = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);
    return () => clearTimeout(timeoutID);
  }, [value, delay]);

  return debouncedValue;
};

export default useDebounce;
```

In the code above, the hook uses the `useState` hook to store the debounced value in `debouncedValue`. The `useEffect` hook is used to update the debounced value whenever the original value or the debouncing delay changes by listing them as dependencies. 

The debouncing logic itself is written inside the `useEffect` hook. Using `setTimeout()`, the variable `debouncedValue` is set to state using the function `setDebouncedValue()`. The method `setTimeout()` returns a timer ID which is saved to the variable `timeoutID`. This ID is later called by `clearTimeout()` in order to clear the timeout function if it is called again within the set time interval.

##Using the Hook

To use the hook, import it and call it into a component. The hook returns the debounced value, which you can then use in your component as needed.

Let's return to our earlier example of the notes app. Here is an extremely simplified example of how we could use this hook in our component:

```javascript
import { useState, useEffect } from "react";
import useDebounce from "./useDebounce";

const App = () => {
  const [value, setValue] = useState("");

  const debouncedValue = useDebounce(value, 2000);

  useEffect(() => {

    //Write Your Function Here!!
    console.log("EXAMPLE FETCH CALL:", debouncedValue);
    
  }, [debouncedValue]);

  const handleChange = (e) => {
    setValue(e.target.value);
  };

  return <textarea onChange={handleChange} />;
};

export default App;
```

In the code above, the component uses the `useDebounce` hook to debounce the `setValue` function. The hook is called with `value` as the first argument and 2000 as the second argument, meaning that the debounced function will be executed after 2000 milliseconds (2 seconds). Another `useEffect` hook is used with the dependency set to `debouncedValue` in order to execute when the debounced value is returned, thus triggering out fetch request.   

And there you have it! In the case of our notes app example described above, the changes to the text input can be automatically committed to the server using this code.

##Resources

Find out more about React hooks in general in the official React Documentation [here](https://reactjs.org/docs/hooks-intro.html).

Find out more about creating custom hooks [here](https://reactjs.org/docs/hooks-custom.html).

##Conclusion

Debouncing is a useful technique for improving the performance and responsiveness of applications. In React, debouncing can be easily implemented using the `setTimeout()` function. By debouncing a function, you can prevent it from being executed too frequently, which can improve the overall performance of your application.