Why we use debouncing and throttling ?
Debouncing and throttling are two commonly used techniques in web development to optimize performance and reduce the load on web servers. These techniques are particularly useful when dealing with events that can trigger multiple times in quick succession, such as user inputs or page scrolling. By implementing debouncing and throttling, we can limit the number of times a function is called and prevent overwhelming the server with requests, resulting in a better user experience and improved website performance.
Debounicng real world example
When you search for something on Flipkart's website, the search results appear as you type. But if every keystroke triggers a request, it could slow down the website. That's where debouncing comes in. It delays the request until you stop typing for a short period of time, ensuring that only the final keystroke triggers the request. This prevents the server from being overloaded with requests and delivers search results quickly.
Lets deep dive into code snippet
export default function App() {
const handleChange = e => {
console.log('api call...')
}
return (
<div className="App">
<header className="App-header">
<p> Search </p>
<input type='text' onChange={handleChange} />
</header>
</div>
);
}
When we search for something in a search box, the number of API requests increases rapidly, which can slow down the website. To address this issue, we use a simple word that doesn't require an API request. However, if we're calling an API for something like searching for a black shirt, every keystroke can trigger a new API request, leading to a flood of requests. To prevent this, we use a technique called "debouncing." Debouncing delays the API request until the user stops typing for a short period of time, so that only the final search term triggers the request. This ensures that the website isn't overwhelmed with requests and delivers search results quickly.
How to implement debounce using react ?
import React, { useState, useEffect } from 'react';
export default function App() {
const [searchTerm, setSearchTerm] = useState('');
useEffect(() => {
const debounceTimer = setTimeout(() => {
console.log('API call with search term:', searchTerm);
// make API call with searchTerm
}, 500);
return () => clearTimeout(debounceTimer);
}, [searchTerm]);
const handleChange = e => {
setSearchTerm(e.target.value);
}
return (
<div className="App">
<header className="App-header">
<p> Search </p>
<input type='text' onChange={handleChange} />
</header>
</div>
);
}
In this example, we're using the useState
hook to create a state variable called searchTerm
, which holds the current value of the search input field. We're also using the useEffect
hook to debounce the API call.
Inside the useEffect
hook, we're setting a timeout of 500 milliseconds. This means that the API call will be made 500 milliseconds after the user stops typing. We're also returning a function that clears the timeout if the searchTerm
changes before the timeout is executed.
In the handleChange
function, we're updating the searchTerm
state with the current value of the input field. This will cause the useEffect
hook to be executed, and the API call will be debounced.
Throttling real world example
A real-world example of throttling is scrolling on a website. When you scroll down a page, the browser fires a scroll event for every pixel you move. If you have a lot of content on the page, this can cause performance issues as the browser tries to handle all the events.
To fix this, we can use throttling to limit the number of scroll events that the browser handles. For example, we might set a limit of one scroll event per 100 milliseconds. This means that the browser will handle only one scroll event during that time, no matter how many times the event is fired.
Throttling ensures that the browser doesn't get overwhelmed with events and that the page stays responsive, even when scrolling through a lot of content.
How to implement debounce using react ?
import React, { useState, useEffect, useCallback } from 'react';
export default function App() {
const [searchTerm, setSearchTerm] = useState('');
// Define a throttled version of the API call function
const throttledAPICall = useCallback(throttle((searchTerm) => {
console.log('API call with search term:', searchTerm);
// make API call with searchTerm
}, 500), []);
useEffect(() => {
throttledAPICall(searchTerm);
}, [searchTerm, throttledAPICall]);
const handleChange = e => {
setSearchTerm(e.target.value);
}
return (
<div className="App">
<header className="App-header">
<p> Search </p>
<input type='text' onChange={handleChange} />
</header>
</div>
);
}
function throttle(func, limit) {
let inThrottle = false;
return function() {
const args = arguments;
const context = this;
if (!inThrottle) {
func.apply(context, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
}
}
In this example, we define a throttle
function that limits the rate at which the API call function is called. We then create a new function throttledAPICall
using useCallback
and throttle
, which will ensure that the API call function is called no more than once every 500 milliseconds.
We pass throttledAPICall
as the callback function to useEffect
. Now, even if the user types rapidly, the API calls will be throttled to prevent overloading the server.
How throttling works?
Throttle function that takes a function func
and a limit
parameter. This function will return a new function that limits the rate at which func is called. The throttled function will only call func
once per limit
milliseconds.
function throttle(func, limit) {
let inThrottle = false;
return function() {
const args = arguments;
const context = this;
if (!inThrottle) {
func.apply(context, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
}
}
Next, we define a new function throttledAPICall
using useCallback
and throttle
. useCallback
is a hook that memoizes a function, so that it only gets redefined when its dependencies change. We pass in throttle
as a dependency, so that the throttledAPICall
function only gets redefined when the throttle limit changes.
const throttledAPICall = useCallback(throttle((searchTerm) => {
console.log('API call with search term:', searchTerm);
// make API call with searchTerm
}, 500), []);
We then use the throttledAPICall
function as the callback function for the useEffect
hook. This means that whenever searchTerm
changes, the throttled API call function will be called instead of the original API call function.
useEffect(() => {
throttledAPICall(searchTerm);
}, [searchTerm, throttledAPICall]);
This ensures that the API calls are throttled to a maximum of once every 500 milliseconds, even if the user types quickly or repeatedly triggers the handleChange
function.
Conclusion
In conclusion, throttling and debouncing are important techniques in optimizing the performance of web applications, especially when it comes to handling user input. Throttling limits the rate at which a function can be called, while debouncing delays a function call until a certain amount of time has passed without the function being called again.
In the case of the search bar example, debounce ensures that an API call is only made after the user has stopped typing for a certain amount of time, while throttle limits the frequency of API calls, preventing excessive requests when the user types too quickly.
Using these techniques can help improve the user experience and reduce the load on the server, making web applications faster and more efficient.
Top comments (0)