How to Abort Axios Requests on Component Unmount
When developing modern frontend applications, navigating away from a
view while asynchronous API requests are still in flight can cause
memory leaks, unnecessary resource consumption, and unwanted state
updates on unmounted components. This guide demonstrates how to use the
standard AbortController interface with the Axios HTTP
client to cleanly and automatically cancel pending requests during a
component's unmount lifecycle.
Understanding AbortController in Axios
Starting with Axios version 0.22.0, Axios natively supports the
web-standard AbortController API, replacing the older and
deprecated CancelToken mechanism.
AbortController allows you to create a signal that can be
passed to one or more HTTP requests, giving you a centralized way to
terminate pending network calls on demand.
Basic Implementation in React
In React, the cleanup function of the useEffect hook
runs when the component unmounts. This makes it the ideal location to
call .abort() on your controller instance.
import React, { useEffect, useState } from 'react';
import axios from 'axios';
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
// 1. Instantiate the AbortController
const controller = new AbortController();
const fetchUserData = async () => {
try {
setLoading(true);
// 2. Pass the controller's signal to the request configuration
const response = await axios.get(`/api/users/${userId}`, {
signal: controller.signal
});
setUser(response.data);
} catch (error) {
// 3. Check if the error is due to cancellation
if (axios.isCancel(error)) {
console.log('Request canceled:', error.message);
} else {
console.error('An unexpected error occurred:', error);
}
} finally {
setLoading(false);
}
};
fetchUserData();
// 4. Clean up and abort pending requests when the component unmounts
return () => {
controller.abort();
};
}, [userId]);
if (loading) return <div>Loading...</div>;
return <div>{user ? user.name : 'No user data'}</div>;
}
export default UserProfile;Aborting Multiple Requests Simultaneously
A single AbortController instance can control multiple
concurrent requests. When you pass the same signal to
multiple Axios calls, executing controller.abort()
terminates every pending request associated with that signal at
once.
useEffect(() => {
const controller = new AbortController();
const loadDashboardData = async () => {
try {
const [stats, activities] = await Promise.all([
axios.get('/api/stats', { signal: controller.signal }),
axios.get('/api/activities', { signal: controller.signal })
]);
setDashboardData({ stats: stats.data, activities: activities.data });
} catch (error) {
if (!axios.isCancel(error)) {
handleError(error);
}
}
};
loadDashboardData();
return () => {
controller.abort();
};
}, []);Handling Cancellation Errors
When a request is aborted, Axios rejects the promise with a
CanceledError. It is essential to differentiate between
standard network or server errors and deliberate cancellations to avoid
displaying false error messages to the user.
- Use
axios.isCancel(error): Returnstrueif the error was triggered by an aborted signal or cancel token. - Check
error.name === 'CanceledError': Alternatively, verify the specific error instance name. - Skip state updates on cancellation: Ensure that
error state setters or toast notifications are bypassed when
axios.isCancel(error)is detected.