DEV Community

Cover image for Create a Debounce Hook for Search Box Auto-Completion
Dylan Oh
Dylan Oh

Posted on • Updated on

Create a Debounce Hook for Search Box Auto-Completion

It is common that we have to implement a search function for the items on a website. Auto-completion is a great feature to improve the searching experience of users.

We know that we can utilize useEffect hook from React to make the fetch API call whenever the input to our search box changes. However, the API call will be fired whenever user types a single character. This might cause some performance issue when the data sets to be searched are growing larger, or if users are having slow internet connection. In order to prevent hitting the API endpoints such frequent, we could implement a debounce function for our auto-complete feature.

Debounce function for making query is a way to slow down the process of querying, and will make the request only after a certain amount of time when user stops typing. The idea is to wrap the state that we want to keep track of with this hook, and only setState after waiting for sometime. After that, in the useEffect hook that calls the API, we are going to use this returned state from the hook to make the API call.

This is how the hook looks like:

import { useState, useEffect } from 'react';

const useDebounce = (value, timeout = 500) => {
    const [state, setState] = useState(value);

    useEffect(() => {
        const handler = setTimeout(() => setState(value), timeout);

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

    return state;
}

export default useDebounce;
Enter fullscreen mode Exit fullscreen mode

The idea is just to use the passed in value (the query text) as the initial state, and listen for the change of value. Whenever the value changes, useEffect hook of this function will get triggered and try to setState after a certain of time (the setTimeout that we defined). However, if user keeps on typing, the useEffect hook will get triggered again and the cleaning of useEffect (the return statement) will run first to clear the previous timeout handler. This is why the state will only return after user stopped typing.

This is how we can use this hook in the fetch call useEffect hook (I only show the minimal amount of code to demonstrate):

import React, { useState, useEffect } from 'react';

const [query, setQuery] = useState("");
const debouncedQuery = useDebounce(query, 500);

useEffect(() => {
            const fetchResults = () => {
                fetch(`https://api.someapi.com/search?q=${debouncedQuery}`)
                .then(result => result.json())
                .then(data => {
                    // parsed the data and set the options
                })
                .catch(err => console.error(err))
            }
            fetchResults();
    }, [debouncedQuery]);
Enter fullscreen mode Exit fullscreen mode

Image description

Click on the link to check out the live demo: Live Demo

Cat Breedy

A single page app that provides the functionality to search for cat breeds and their pictures.

Frontend: React, Ant Design Library
API: The Cat API

This is my second time using Ant Design library and it is getting more and more handy.

Please check out the live demo here:

Cat Breedy

You will be greeted with a landing page. Click on "Explore" to start the search.

cat_breedy_landing

When you landed on the search route, all 67 breeds will be fetched and paginated (9 in a page). You can click through all the pages.

Start searching for cat breeds, typing in "American" in the search box. You will expect to see the suggestions dropdown after 1 second (I think it would be better to put 500ms) as custom debounce hook is wrapped on the query.

Images are lazy loaded with Carousel component in Ant Design. React Slicker is working underneath…

Do follow me for more future articles on web design, programming and self-improvement 😊

Discussion (0)