In React applications, it’s common to have buttons triggering HTTP requests. However, a challenge arises when users rapidly click the same button, potentially leading to multiple redundant API calls. In this blog post, we’ll explore strategies to avoid making duplicate HTTP requests using the JSONPlaceholder API as a real-world example.
The Problem: Duplicate Requests
Consider a scenario where you have a button that fetches user data from the JSONPlaceholder API when clicked. Without any precautionary measures, users might click the button multiple times in quick succession, resulting in redundant API calls.
Example: Fetching User Data
import React, { useState } from 'react';
const UserFetcher = () => {
const [userData, setUserData] = useState(null);
const fetchUserData = async () => {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/users/1');
const data = await response.json();
setUserData(data);
} catch (error) {
console.error('Error fetching user data:', error);
}
};
return (
<div>
<button onClick={fetchUserData}>Fetch User Data</button>
{userData && (
<div>
<h2>{userData.name}</h2>
<p>Email: {userData.email}</p>
{/* Display other user data */}
</div>
)}
</div>
);
};
export default UserFetcher;
In this example, the fetchUserData
function is triggered when the button is clicked, fetching user data from the JSONPlaceholder API. However, if the user clicks the button rapidly, it may result in unnecessary API calls.
Solution 1: Disable Button During Request
One simple solution is to disable the button while the API request is in progress, preventing users from triggering multiple requests simultaneously.
Example: Disabling Button
// ... (imports and component definition)
const UserFetcher = () => {
const [userData, setUserData] = useState(null);
const [isLoading, setIsLoading] = useState(false);
const fetchUserData = async () => {
try {
setIsLoading(true);
const response = await fetch('https://jsonplaceholder.typicode.com/users/1');
const data = await response.json();
setUserData(data);
} catch (error) {
console.error('Error fetching user data:', error);
} finally {
setIsLoading(false);
}
};
return (
<div>
<button onClick={fetchUserData} disabled={isLoading}>
{isLoading ? 'Fetching...' : 'Fetch User Data'}
</button>
{userData && (
<div>
<h2>{userData.name}</h2>
<p>Email: {userData.email}</p>
{/* Display other user data */}
</div>
)}
</div>
);
};
export default UserFetcher;
By introducing the isLoading
state, we can disable the button when a request is in progress. This prevents users from triggering multiple requests simultaneously and ensures that the button is only clickable when the API call is complete.
Solution 2: Throttle or Debounce User Clicks
Another approach is to use a debounce or throttle function to limit the frequency of API calls. This prevents multiple rapid clicks from triggering separate requests.
Using Lodash for Debouncing
npm install lodash
Example: Debouncing Clicks
import React, { useState } from 'react';
import _ from 'lodash';
const UserFetcher = () => {
const [userData, setUserData] = useState(null);
// Debounce the fetchUserData function to limit rapid clicks
const debouncedFetchUserData = _.debounce(async () => {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/users/1');
const data = await response.json();
setUserData(data);
} catch (error) {
console.error('Error fetching user data:', error);
}
}, 1000); // 1000ms debounce time
return (
<div>
<button onClick={debouncedFetchUserData}>Fetch User Data</button>
{userData && (
<div>
<h2>{userData.name}</h2>
<p>Email: {userData.email}</p>
{/* Display other user data */}
</div>
)}
</div>
);
};
export default UserFetcher;
In this example, the debouncedFetchUserData
function is created using the debounce
function from lodash. This function ensures that the original function (fetchUserData
) is only called after a specified delay (in this case, 1000ms). Rapid clicks within this time frame won’t trigger additional API requests.
Conclusion
Effectively handling multiple clicks on the same button in a React application is crucial to optimizing performance and resource usage. By either disabling the button during the request or employing a debounce mechanism, you can prevent redundant API calls and provide a smoother user experience. Choose the approach that best fits your application’s requirements and complexity. Happy coding!