javascript / intermediate
Snippet
Cancelling In-Flight HTTP Requests on Component Unmount with AbortController
Instantiating an `AbortController` inside `useEffect` connects the DOM lifecycle to ongoing asynchronous `fetch` calls. Returning `controller.abort()` in the cleanup function aborts in-flight network promises when the query changes or the component unmounts, while checking `err.name !== 'AbortError'` suppresses intentional cancellations.
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
31
32
33
34
35
36
37
function SearchResults({ query }) {const [results, setResults] = React.useState([]);const [isLoading, setIsLoading] = React.useState(false);React.useEffect(() => {const controller = new AbortController();const { signal } = controller;async function performSearch() {setIsLoading(true);try {const response = await fetch(`/api/search?q=${encodeURIComponent(query)}`, { signal });const data = await response.json();setResults(data);} catch (err) {if (err.name !== 'AbortError') {console.error('Fetch operation failed:', err);}} finally {setIsLoading(false);}}if (query) performSearch();return () => {controller.abort();};}, [query]);return (<div>{isLoading && <span>Searching...</span>}<ul>{results.map((r) => <li key={r.id}>{r.title}</li>)}</ul></div>);}
react
Breakdown
1
const controller = new AbortController();
Creates a cancellation signal provider specifically for the current effect execution lifecycle.
2
const response = await fetch(..., { signal });
Passes the abort signal to the fetch API to support hardware and network-level termination.
3
if (err.name !== 'AbortError') {
Filters out expected abort exceptions to prevent treating intentional unmounts as real errors.