How to improve search in React using Debouncing

Debouncing will help you avoid overloading the server and optimize application performance. Below are detailed instructions.

Debouncing will help you avoid overloading the server and optimize application performance. Below are detailed instructions.

Picture 1 of How to improve search in React using Debouncing

In React, when implementing search functionality, the onChange handler calls the search function each time the user types inside the input box. This method can cause performance errors, especially when making API calls or database queries. Frequent calls to the search function can overload the web server, causing the UI to become unresponsive. Debouncing will solve this problem.

What is Debouncing?

Specifically, you implement a search function in React by calling an onChange handler function on each keystroke as follows:

import { useState } from "react"; export default function Search() { const [searchTerm, setSearchTerm] = useState(""); const handleSearch = () => { console.log("Search for:", searchTerm); }; const handleChange = (e) => { setSearchTerm(e.target.value); // Calls search function handleSearch(); }; return ( ); }

 While the above code works, calling the backend to update search results on every keystroke can be expensive. For example, if you are looking for 'webdev', the application will send a query to the backend with the values ​​'w', 'we', 'web', etc.

Debouncing is a technique that works by delaying the execution of a function until the delay expires. The debounce function detects each keystroke by the user and prevents calls to the search handler until the delay expires. If the user continues typing during the delay, the timer is reset and React calls the function again for the new delay. This process continues until the user stops typing.

By waiting for the user to pause typing, debouncing ensures the application only performs necessary search queries, thereby reducing server load.

How to debounce search in React

There are several libraries you can use to implement debounce. You can also choose to implement it yourself from scratch using the JavaScript setTimeout and clearTimeout functions.

This article uses the debounce function from the lodash library. Assuming you have an existing React project, create a new component named Search. If you don't have an active project yet, create a React app using create-react-app.

In the Search component file, copy the following code to create a search input box that calls the handler function on each keystroke.

import { useState } from "react"; export default function Search() { const [searchTerm, setSearchTerm] = useState(""); const handleSearch = () => { console.log("Search for:", searchTerm); }; const handleChange = (e) => { setSearchTerm(e.target.value); // Calls search function handleSearch(); }; return ( ); }

To debounce the handleSearch function , convert it to the debounce function from lodash.

import debounce from "lodash.debounce"; import { useState } from "react"; export default function Search() { const [searchTerm, setSearchTerm] = useState(""); const handleSearch = () => { console.log("Search for:", searchTerm); }; const debouncedSearch = debounce(handleSearch, 1000); const handleChange = (e) => { setSearchTerm(e.target.value); // Calls search function debouncedSearch(); }; return ( ); }

 In the debounce function , you are passing to the function you want to delay, e.g. handleSearch, the delay time is in milliseconds, e.g. 500ms.

While the above code will delay calling the handleSearch query until the user pauses typing, it does not work in React.

Debouncing and Rendering

This application uses input control. That means the state value controls the input value. Each time the user enters the search field, React updates this state.

In React, when the state value is changed, React shows the component and implements all the functions inside it.

In the above search component, when rendering the component again, React runs the debounce function. This function creates a new stopwatch, continuously monitors the delay, and the old stopwatch remains in memory. When the timer expires, it activates the search feature. This means the search function is never debounced, it is delayed by about 500ms. This cycle repeats on each render - the function creates a new timer, the old one expires, then it calls the search function.

For the debounce function to work, you only have to call it once. You can do this by calling the debounce function outside the component or by using mnemonics. This way, even if the component is visible, React won't run it again.

Define the debounce function outside the search component

Move the debounce function outside the search element like below:

import debounce from "lodash.debounce" const handleSearch = (searchTerm) => { console.log("Search for:", searchTerm); }; const debouncedSearch = debounce(handleSearch, 500); 

Now in the Search component , call debouncedSearch and pass it the search term.

export default function Search() { const [searchTerm, setSearchTerm] = useState(""); const handleChange = (e) => { setSearchTerm(e.target.value); // Calls search function debouncedSearch(searchTerm); }; return ( ); }

This search function will only be called after the delay period ends.

Memoizing the Debounce function

Memoizing refers to saving the results of a function and reusing them when you call the function with the same arguments.

To memoize the debounce function , use the useMemo hook .

import debounce from "lodash.debounce"; import { useCallback, useMemo, useState } from "react"; export default function Search() { const [searchTerm, setSearchTerm] = useState(""); const handleSearch = useCallback((searchTerm) => { console.log("Search for:", searchTerm); }, []); const debouncedSearch = useMemo(() => { return debounce(handleSearch, 500); }, [handleSearch]); const handleChange = (e) => { setSearchTerm(e.target.value); // Calls search function debouncedSearch(searchTerm); }; return ( ); }

 Note that you also wrap the handleSearch function in the useCallback hook to ensure React only calls it once. Without the useCallback hook , React would run the handleSearch function with each re-render, causing the dependencies of the useMemo hook to change, which in turn would call the debounce function .

Now, React will only call the debounce function if handleSearch or the delay changes.

In short, debounce will help programmers reduce queries to the server because it only sends queries after the delay has expired and the user has paused typing. Thanks to that, the server is not overloaded and the application performance is improved.

Update 13 October 2023
Category

System

Mac OS X

Hardware

Game

Tech info

Technology

Science

Life

Application

Electric

Program

Mobile