0 day streak
javascript / intermediate
Snippet

Cancelling In-Flight Async Fetch Requests in React Effects via AbortController

When fetching data in a useEffect hook, rapid prop changes or unmounting can cause race conditions and memory leaks. By pairing standard Web API AbortController with the fetch signal option, in-flight HTTP requests are cleanly aborted in the effect's cleanup function, ignoring expected 'AbortError' exceptions.

snippet.js
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import { useState, useEffect } from 'react';
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
const controller = new AbortController();
const { signal } = controller;
async function loadUserData() {
try {
const res = await fetch(`/api/users/${userId}`, { signal });
const data = await res.json();
setUser(data);
} catch (err) {
if (err.name !== 'AbortError') {
console.error('Fetch failed:', err);
}
}
}
loadUserData();
return () => {
controller.abort();
};
}, [userId]);
return user ? <div>{user.name}</div> : <p>Loading...</p>;
}
react
Breakdown
1
const controller = new AbortController();
Instantiates a new controller to generate a cancellation signal for async operations.
2
const res = await fetch(`/api/users/${userId}`, { signal });
Passes the controller's abort signal to fetch to link network request lifecycle with component lifecycle.
3
if (err.name !== 'AbortError') {
Differentiates intentional cancellations triggered by cleanup from actual network or parsing failures.
4
return () => { controller.abort(); };
Cleanup callback invoked by React when dependencies change or on unmount, aborting the pending request.