Understanding debouncing in React application.

What is debouncing in layman's terms???

Debouncing means limiting the rate at which function gets executed in the application. It prevents the unwanted repetitive function call within a short timeframe.

For example you’ve created an application which has a search functionality. Now, in every key stroke, the api is being called repeatedly (we’ve all been there in this situation). As a result, the app behaves in an undesirable manner.

How to prevent it??? Debouncing is the answer! And it’s really simple, trust me.

Setting up the environment

Set up your react application. Let’s take up an example. We have created a react app where the search functionality is implemented.

import React, {useState} from "react"

export default App () {
    const [list, setList] = useState([]);
    const [search, setSearch] = useState("");

    useEffect(() => {
      const loadUsers = async () => {
           const data = await fetch(search);
           setList(data);
      }
      loadUsers();
    }, [search])

    return (
      <div>
        <input value={search} onChange={(e)=>setSearch(e.target.value)}
        {list.map((names) => return names)}
      </div>
    )

Look carefully in the above code. The useEffect runs everytime the search value changes. As a result the fetch request is done on every keystroke when the user wants to type the name.

That’s not the main problem. Whenever multiple keys are being pressed, the requests is sent for each keystroke without waiting for the previous keystroke’s request to be fulfilled. As a result, the behaviour is unpredictable.

Let’s understand by taking a basic example. Suppose we want to search the name “rohan”. The request will get fired on every keystroke. Even if the request isn’t fulfilled for the previous key pressed, it’ll still be called. As a result, it will give flickering output.

Solution:

The solution is very simple. Let’s understand the main context first!
When we search the word “rohan”, all we care is about the last letter. We don’t need to send request for “r” or “o” or “h” or “a”. We need to send request only when user presses the last letter, here: “n”. But how will we know that this letter is the final letter…as it all depends on what user is going to type. Well, we can get to know this by the delay in typing. If the user delays more than certain amount of time, we’ll assume the last letter to be the final letter and the word formed will be passed to search in the api. That’s it!

Steps:

Let’s create a debouncing hook to manage this situation!

Step 1: Create a hooks folder.

Step 2: Create a file and name it (useDebounce.tsx imo)

Step 3: Create the useDebounce hook. Understand the code below.

export default useDebounce = (name, duration=500) => {
    const [debouncedValue, setDebouncedValue] = useState("");

    useEffect(() => {
        const timeout = setTimeout(() => {
            setDebouncedValue(name);
        }, duration)

        return () => clearTimeout(timeout);
    }, [name, duration])

    return {debouncedValue};
}

useDebounce() hook code explanation:

This hook gets 2 parameters, name and duration (I’ve kept the duration with default value: 500 ms).

This component has a useEffect hook which contains setTimeout function. This function will run everytime the name value from the props changes as it is in the dependency array.

If the value changes within 500ms, the useEffect will again be called and previous timeout will be cleared by return value.
If it doesn’t change before 500ms, the debounced value will be our assumed current word and it will be returned.

Use this debounce hook in your main component.

import React, {useState} from "react"
import useDebounce from "./useDebounce.tsx"

export default App () {
    const [list, setList] = useState([]);
    const [search, setSearch] = useState("");

    const {debouncedValue} = useDebounce(search);

    useEffect(() => {
      const loadUsers = async () => {
           const data = await fetch(debouncedValue);
           setList(data);
      }
      loadUsers();
    }, [debouncedValue])

    return (
      <div>
        <input value={search} onChange={(e)=>setSearch(e.target.value)}
        {list.map((names) => return names)}
      </div>
    )

Here, we’re returning the debounced value from useDebounce hook which is passed to fetch the data in the useEffect. If user stops typing for more than 500ms, the useDebounce hook will come in action and debouncedValue will be used to fetch the data accordingly.

That’s how you can use useDebounce hook in your React application and optimise its performance. Thankyou for reading!

1
Subscribe to my newsletter

Read articles from Rohan Kumar Pandey directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Rohan Kumar Pandey
Rohan Kumar Pandey

Hey!👋🏽 Myself Rohan from Bengaluru. I'm a frontend developer at weweonbase. -🔭 I've worked in GWOC'21 as a Contributor in Front-end development. -🔭I've won Hacktoberfest'21 by making 4 valid contributions. -🔭I got selected to participate in Script Winter of Contributing. 🌱 Currently I'm learning Dev-ops fundamentals. 👯 I’m looking for opportunities and learning new skills during the process.