How to Cancel API Calls in React with Axios: A Step-by-Step Guide
Nilesh Kumar
Posted on November 14, 2024
Learn how to manage multiple API calls in React by canceling
previous requests with Axios. This guide shows you how to use Axios’s CancelToken
to cancel requests that are no longer needed. By doing this, you can improve performance and reduce unnecessary network traffic when users switch between selections, like changing stories in a React component.
In modern web apps, especially those built with React, it’s common to fetch data from APIs when users take actions, like clicking on a story or selecting a product. However, if a user triggers multiple actions quickly, previous requests might still be running in the background, using up resources and potentially showing outdated or incorrect data.
In this post, we’ll show you how to solve this problem by canceling ongoing Axios requests whenever a user picks a new item. This helps avoid unnecessary API calls, boosts performance, and makes sure you get the most up-to-date data. Let’s go through the solution with an easy example!
Understanding the Problem:
Imagine you have a React component that loads audio for a story from an API every time a user selects a new story. But if the user quickly switches between stories, the previous API requests might still be running in the background. This can lead to extra load on the server, delays, and problems like playing the wrong audio.
To solve this, we need to cancel the previous request when a new request is triggered.
Using Axios Cancellation Tokens in React
To cancel ongoing requests, we’ll use Axios’s CancelToken
. This lets us stop a request if it’s not needed anymore, like when a user picks a different story before the previous request is done. Here’s how you can set this up in a React component:
Step 1: Create a Cancellation Token
First, we need to create a reference that stores the cancellation token. We can use the useRef
hook in React to persist the token across re-renders of the component.
const cancelTokenSource = useRef(null);
Step 2: Cancel Previous Request Before Making a New One
Before we make a new API call, we check if there’s an existing request. If there is, we cancel it. We do this by calling cancel()
on the current cancelTokenSource.
if (cancelTokenSource.current) {
cancelTokenSource.current.cancel('Operation canceled due to new request.');
}
Step 3: Create a New Cancellation Token for Each Request
After canceling the previous request, we create a new cancel token source for the next API call.
cancelTokenSource.current = axios.CancelToken.source();
Step 4: Make the API Request with the Cancel Token
Now, when we make the actual API request, we pass the cancel token along with the request. This ensures that the request can be canceled if needed.
const response = await axios.get(url, {
cancelToken: cancelTokenSource.current.token,
});
Step 5: Handle Request Cancellation
In the catch block, we handle the cancellation error separately. If the request was canceled, we log a message and do not treat it as a real error.
catch (error) {
if (axios.isCancel(error)) {
console.log('Request canceled:', error.message);
} else {
// Handle other errors
console.log('API call error:', error);
}
}
Example Code: Full React Component Implementation
Here’s the full implementation of the solution in a React component that fetches a story’s audio when the user selects a story:
import React, { useState, useEffect, useRef } from 'react';
import axios from 'axios';
import { toast } from 'react-toastify';
const StorySpeechComponent = ({ id }) => {
const [base64audio, setBase64audio] = useState(null);
const cancelTokenSource = useRef(null); // Store the cancel token
const getStorySpeech = async (id) => {
if (cancelTokenSource.current) {
cancelTokenSource.current.cancel('Operation canceled due to new request.');
}
cancelTokenSource.current = axios.CancelToken.source();
try {
const url = `http:/localhost:8000/api/v1/getAudio/${id}`; // update your api url here
const response = await axios.get(url, {
cancelToken: cancelTokenSource.current.token, // creating the canel token for the api
});
if (response?.data?.audio) {
setBase64audio(response.data.audio); // save your response to any state as requre
}
} catch (error) {
if (axios.isCancel(error)) {
console.log('Request canceled:', error.message);
} else {
console.log('Get Story Speech API error:', error.response);
if (error.response?.status === 400) {
toast.error(error.response.data["non_field_errors"][0]);
}
}
}
};
useEffect(() => {
if (id) {
getStorySpeech(id);
}
return () => {
if (cancelTokenSource.current) {
cancelTokenSource.current.cancel('Component unmounted or story changed.');
}
};
}, [id]); // Re-fetch when the selected story Id changes
return (
<div>
<h1>Story Speech</h1>
{base64audio ? (
<audio controls>
<source src={`data:audio/mp3;base64,${base64audio}`} type="audio/mp3" />
Your browser does not support the audio element.
</audio>
) : (
<p>Loading audio...</p>
)}
</div>
);
};
export default StorySpeechComponent;
Conclusion:
By using Axios’s cancellation feature, we can avoid unnecessary network requests and keep our React app running smoothly. This is especially helpful when multiple API calls are triggered quickly, like when users are switching between different items. This simple approach boosts performance and improves the user experience by preventing race conditions and cutting down on unnecessary API calls.
Posted on November 14, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.