0
0
ReactHow-ToBeginner · 4 min read

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 AbortError to handle it gracefully without showing user errors.
  • Reusing the same controller: Create a new AbortController for 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:

ActionDescriptionCode Example
Create controllerMake a new AbortController instanceconst controller = new AbortController();
Get signalPass signal to fetch to enable abortingfetch(url, { signal: controller.signal })
Abort fetchCancel the fetch requestcontroller.abort();
Handle abort errorCheck if error is due to abortif (error.name === 'AbortError') { /* handle */ }
Cleanup in ReactAbort fetch in useEffect cleanupreturn () => 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.