AbortController in JavaScript and React — Explained for Beginners

Yash GroverYash Grover
4 min read

Have you ever started something and then realized you didn’t need to finish it? Maybe you ordered a pizza but changed your mind and made maggi instead. Wouldn’t it be nice if you could call the delivery guy and say:
“Stop! I don’t need that pizza anymore.”

That’s exactly what AbortController does in JavaScript.

AbortController lets you stop async operations you no longer need - usually used for network requests but can also be used for file operations, DOM event listeners, timers, streaming operations, and custom async tasks - saving time, memory, and avoiding messy bugs.

What is AbortController?

AbortController is a built-in browser API that gives you control over asynchronous operations — mainly network requests using fetch().
It has two parts:

  • controller — the “remote control”

  • signal — the “wire” that connects your request to the controller

When you call controller.abort(), any request linked to its signal will immediately stop. ( Don’t worry we will dive deep into this soon ! )

Why do we need it?

Before AbortController, once you started a fetch request:

  • You had to wait until it finished — even if you didn’t need the result anymore.

  • If you tried to update your app after the component disappeared (like in React), you could get warnings like:
    “Can't perform a React state update on an unmounted component.”

This caused:

  • Memory leaks — unused requests still running

  • Race conditions — slow responses overwriting newer ones

  • Annoying errors — because your code tried to update something that no longer exists

How Does It Work?

Basic Example in JavaScript

const controller = new AbortController();     // 1. Create controller
const signal = controller.signal;             // 2. Get signal

fetch("https://jsonplaceholder.typicode.com/posts", { signal })
  .then(res => res.json())
  .then(data => console.log(data))
  .catch(err => {
    if (err.name === "AbortError") {
      console.log("Request was aborted!");
    } else {
      console.error("Fetch failed:", err);
    }
  });

// Later (maybe user navigated away)
controller.abort();  // Stop the request
  • When you call abort(), the fetch stops immediately and throws an AbortError.

Using AbortController in React

React components mount and unmount as users navigate around.
If a fetch is still running after a component unmounts, React may try to update state that no longer exists.
To avoid this, cancel your requests inside a cleanup function using AbortController.

import { useEffect, useState } from "react";

function UserList() {
  const [users, setUsers] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const controller = new AbortController();

    fetch("https://jsonplaceholder.typicode.com/users", { signal: controller.signal })
      .then(res => res.json())
      .then(data => {
        setUsers(data);
        setLoading(false);
      })
      .catch(err => {
        if (err.name === "AbortError") {
          console.log("Fetch aborted");
        }
      });

    return () => controller.abort(); // Cancel when component unmounts
  }, []);

  if (loading) return <p>Loading...</p>;
  return (
    <ul>
      {users.map(user => <li key={user.id}>{user.name}</li>)}
    </ul>
  );
}

Modern Real-World Uses

1. Cancel Old Searches When New Ones Start

Perfect for search bars or autocomplete:

let controller;

async function search(query) {
  if (controller) controller.abort(); // Cancel previous request
  controller = new AbortController();

  try {
    const res = await fetch(`/api/search?q=${query}`, { signal: controller.signal });
    const data = await res.json();
    console.log("Results:", data);
  } catch (err) {
    if (err.name === "AbortError") console.log("Old search aborted");
  }
}

2. Cancel Multiple Requests Together

const controller = new AbortController();

Promise.all([
  fetch('/api/1', { signal: controller.signal }),
  fetch('/api/2', { signal: controller.signal })
])
.catch(err => {
  if (err.name === 'AbortError') console.log('Both requests aborted');
});

controller.abort(); // Cancels all at once

AbortController with Axios

Old Way (Before Axios v0.22)

Axios had a custom CancelToken API.

Modern Way (Axios v0.22+)

Axios now supports AbortController natively:

const controller = new AbortController();

axios.get('/user', { signal: controller.signal })
  .then(res => console.log(res.data))
  .catch(err => {
    if (err.code === 'ERR_CANCELED') console.log('Request canceled!');
  });

// Cancel the request when needed
controller.abort();

This matches the browser standard and works just like fetch.


Key Takeaways

  • What it is: A remote control to stop async operations like fetch.

  • Why it matters: Prevents wasted work, race conditions, and React warnings.

  • How to use it: Create a controller → pass signal to your request → call abort() when done.

  • Modern support: Native in fetch, supported in Axios and most libraries.


Final Analogy to Remember

Think of AbortController as a remote control for network requests:

  • You plug in the “wire” (signal) into your request.

  • If you no longer need that request — maybe you switched pages or started a new search —

  • You press STOP (controller.abort()), and the request vanishes instantly.

No more cold pizza deliveries you didn’t ask for! 🍕


In short:

AbortController = less wasted work, fewer bugs, happier apps.

0
Subscribe to my newsletter

Read articles from Yash Grover directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Yash Grover
Yash Grover