
AbortController in React
AbortController lets you cancel in-flight fetch requests. In React, this is essential for cleaning up effects that start async operations.
The Problem Without Cleanup
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
fetch(`/api/users/${userId}`)
.then(r => r.json())
.then(setUser); // may run after component unmounts or userId changes
}, [userId]);
} If userId changes or the component unmounts while the fetch is in flight, setUser runs on stale or dead state.
AbortController Solution
useEffect(() => {
const controller = new AbortController();
fetch(`/api/users/${userId}`, { signal: controller.signal })
.then(r => r.json())
.then(setUser)
.catch(err => {
if (err.name === 'AbortError') return; // expected — ignore
setError(err);
});
return () => controller.abort(); // cancel on cleanup
}, [userId]); When userId changes, the old effect cleans up (controller.abort()), cancelling the previous fetch before the new one starts.
Multiple Requests
One controller can abort multiple requests:
useEffect(() => {
const controller = new AbortController();
const { signal } = controller;
Promise.all([
fetch('/api/user', { signal }).then(r => r.json()),
fetch('/api/posts', { signal }).then(r => r.json()),
]).then(([user, posts]) => {
setUser(user);
setPosts(posts);
}).catch(err => {
if (err.name !== 'AbortError') setError(err);
});
return () => controller.abort();
}, []); Timeout with AbortSignal
// Manual timeout
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 5000);
fetch(url, { signal: controller.signal }).finally(() => clearTimeout(timeoutId));
// Newer API
fetch(url, { signal: AbortSignal.timeout(5000) }); Custom Hook
function useFetch(url) {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const controller = new AbortController();
setLoading(true);
fetch(url, { signal: controller.signal })
.then(r => r.json())
.then(setData)
.catch(err => { if (err.name !== 'AbortError') setError(err); })
.finally(() => setLoading(false));
return () => controller.abort();
}, [url]);
return { data, error, loading };
} StrictMode and Double-Fetch
React StrictMode mounts → unmounts → remounts in dev. The abort cleanup between the two mounts cancels the first fetch. This is expected — the second mount starts a fresh request. Ensure your cleanup is correct and the AbortError is handled.
Browser support snapshot
Live support matrix for abortcontroller from
Can I Use.
Show static fallback image

Source: caniuse.com









