How to Use Abort Controller in React for Canceling Fetch Requests
In React, use
AbortController to cancel fetch requests by creating an instance and passing its signal to the fetch call. Call abort() on the controller inside useEffect cleanup to stop the request when the component unmounts or dependencies change.Syntax
The AbortController API lets you create a controller object that can abort one or more fetch requests. You create it with new AbortController(). The controller has a signal property, which you pass to fetch as an option. Calling abort() on the controller cancels the fetch.
In React, you typically create the controller inside a useEffect hook and call abort() in the cleanup function to cancel ongoing requests when the component unmounts or updates.
javascript
useEffect(() => {
const controller = new AbortController();
fetch(url, { signal: controller.signal })
.then(response => response.json())
.then(data => setData(data))
.catch(error => {
if (error.name === 'AbortError') {
console.log('Fetch aborted');
} else {
console.error('Fetch error:', error);
}
});
return () => {
controller.abort();
};
}, [url]);Example
This example shows a React functional component that fetches user data from an API. It uses AbortController to cancel the fetch if the component unmounts before the request finishes, preventing memory leaks and errors.
javascript
import React, { useState, useEffect } from 'react'; function UserProfile({ userId }) { const [user, setUser] = useState(null); const [error, setError] = useState(null); useEffect(() => { const controller = new AbortController(); const signal = controller.signal; async function fetchUser() { try { const response = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`, { signal }); if (!response.ok) throw new Error('Network response was not ok'); const data = await response.json(); setUser(data); } catch (err) { if (err.name === 'AbortError') { console.log('Fetch aborted'); } else { setError(err.message); } } } fetchUser(); return () => { controller.abort(); }; }, [userId]); if (error) return <p>Error: {error}</p>; if (!user) return <p>Loading user data...</p>; return ( <div> <h2>{user.name}</h2> <p>Email: {user.email}</p> <p>Phone: {user.phone}</p> </div> ); } export default UserProfile;
Output
<p>Loading user data...</p> then renders user name, email, and phone after fetch completes
Common Pitfalls
- Not aborting fetch on unmount: This can cause memory leaks or React warnings about state updates on unmounted components.
- Ignoring abort errors: Always check if the error is an
AbortErrorto handle it gracefully without showing user errors. - Reusing the same controller: Create a new
AbortControllerfor each fetch to avoid unexpected cancellations.
javascript
/* Wrong: Not aborting fetch on unmount */ useEffect(() => { fetch(url) .then(res => res.json()) .then(data => setData(data)); }, [url]); /* Right: Abort fetch on unmount */ useEffect(() => { const controller = new AbortController(); fetch(url, { signal: controller.signal }) .then(res => res.json()) .then(data => setData(data)) .catch(err => { if (err.name !== 'AbortError') { console.error(err); } }); return () => controller.abort(); }, [url]);
Quick Reference
AbortController Cheat Sheet:
| Action | Description | Code Example |
|---|---|---|
| Create controller | Make a new AbortController instance | const controller = new AbortController(); |
| Get signal | Pass signal to fetch to enable aborting | fetch(url, { signal: controller.signal }) |
| Abort fetch | Cancel the fetch request | controller.abort(); |
| Handle abort error | Check if error is due to abort | if (error.name === 'AbortError') { /* handle */ } |
| Cleanup in React | Abort fetch in useEffect cleanup | return () => controller.abort(); |
Key Takeaways
Always create a new AbortController for each fetch to control cancellation.
Pass the controller's signal to fetch to enable aborting the request.
Call abort() in useEffect cleanup to prevent memory leaks on unmount.
Handle AbortError separately to avoid showing unnecessary errors.
Using AbortController improves app performance and user experience by stopping unwanted fetches.