How to improve search in React using Debouncing
Debouncing will help you avoid overloading the server and optimize application performance. Below are detailed instructions.
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.
You should read it
- How to detect clicks outside a React component using a custom hook
- How to use Sass in React
- Instructions for creating a Tic-Tac-Toe game using React-Native
- Tooltip creation tools are useful with ReactJS
- React mistakes to avoid for successful app development
- How to manage state in React using Jotai
- How to speed up React apps with code splitting
- How to create a Hacker News clone using React
May be interested
- Full Stack JavaScript: What are MERN, MEAN and MEVN?mern, mean, and mevn are the most popular stacks for full-stack application development. but what is the difference between mern, mean and mevn in full stack javascript?
- How to use Slot in Svelteslot makes it easier to transfer data from one component to another. let's learn how to use slot in svelte to create dynamic components!
- Misconceptions about UI/UX design debunkedfollowing misconceptions and misconceptions about ui/ux design can make it difficult for you to grow. therefore, don't make the ui/ux design mistakes below.
- Things to know about event-driven programming in Node.jsnode's powerful event-driven architecture is one of its strongest advantages. here's everything you need to know about event-driven programming in node.js.
- How to manage resources in Python using a context managerensuring efficient resource management with a context manager in python is easy. below are detailed instructions.
- How to build a Paint application with Pythonprogramming a painting application is a basic exercise that will teach you a lot about gui programming. below are instructions on how to create a painting application in python.