Skip to main content

Cancel API requests in React: Axios, AbortController, and debounce explained

Posted By

Sachin Warke

Date Posted
29-Apr-2026

When users type into a search field, your app fires an API call on each input change. Fast typists can trigger five requests in a second. The problem is not the number of calls — it is that responses arrive out of order. An older, slower request can resolve after a newer one, and the newer one can overwrite the correct results on screen.

This guide shows exactly how to cancel API requests in React using AbortController, paired with debounce, so only the latest request ever updates the UI.

The race condition problem

Here is what happens without request cancellation:

  1. User types "re" → Request A fires
  2. User types "rea" → Request B fires
  3. Request B resolves first → UI shows correct results for "rea"
  4. Request A resolves late → UI is overwritten with stale results for "re"

This is a race condition. The UI displays data from an older query, not the one the user is currently looking at.

Without cancellation vs. with AbortController:

Without Cancellation With AbortController
Stale results overwrite fresh ones Previous request aborted before next fires
UI shows incorrect data UI only updates from the latest request
Every in-flight request runs to completion Aborted requests free up network resources
Unnecessary backend load Cleaner, predictable state

AbortController

Why this matters

  • Incorrect results are displayed to the user.
  • Race conditions cause unpredictable UI behavior.
  • Every in-flight request adds unnecessary load to your backend.
  • Users lose trust in the search experience.

The solution: Cancel previous requests

Cancel the previous API call before firing a new one. This guarantees that only the latest request can update the UI. The browser drops the old request, and your state stays clean.

Why does debounce alone not fix this?

Debounce reduces how often a function fires by waiting for a pause in user input. It delays the API call — it does not cancel one that is already in flight.

If a request takes longer than the debounce delay, you are back to the same race condition. Debounce and request cancellation solve different problems. You need both.

Technique Reduces API Call Frequency Cancels In-Flight Requests
Debounce Yes No
AbortController No Yes
Both together Yes Yes

How AbortController works

AbortController is a native browser API. It gives you a signal object that you pass to a fetch or Axios request. Calling .abort() on the controller sends a cancellation signal to that request. The browser then stops processing it.

Axios supports AbortController natively via the signal config option. When a request is aborted, Axios throws an error with the code ERR_CANCELED.

How AbortController works

Implementation (React + Axios + AbortController)

Here is what the implementation involves, before we walk through each step:

  • Step 1: Create a controller reference
  • Step 2: Cancel the previous request before making a new one
  • Step 3: Use debounce
  • Step 4: Trigger on input change

Full code example

The following is the complete implementation. The code requires React and Axios.

const controllerRef = useRef(null);

const fetchSearchResults = async (query) => {
  if (controllerRef.current) {
    controllerRef.current.abort();
  }

  controllerRef.current = new AbortController();

  try {
    const response = await axios.get("/api/search", {
      params: { q: query },
      signal: controllerRef.current.signal,
    });
    console.log(response.data);
  } catch (error) {
    if (error.code === "ERR_CANCELED") {
      console.log("Request canceled");
    } else {
      console.error(error);
    }
  }
};

What happens when a request is aborted

On the client: Axios throws an error with error.code === "ERR_CANCELED". This is expected behavior, not an application error. Catch it explicitly and handle it silently — do not show an error message to the user for a canceled request.

On the server: Aborting a request closes the connection from the client side. Whether the server stops processing depends on the server implementation. Most Node.js servers will terminate the request handler when the client disconnects, but this is not guaranteed across all backends. The primary benefit of AbortController is on the client: it prevents stale responses from updating the UI.

Common mistakes to avoid

  1. Not checking for ERR_CANCELED: If you catch all errors the same way, aborted requests are logged as failures. Always check error.code === "ERR_CANCELED" before deciding how to handle the error.
  2. Creating a new controller without aborting the old one: Always abort the previous controller before creating a new one. Skipping the abort step defeats the purpose — the old request stays in flight.
  3. Using useState for the controller: Storing the AbortController in state causes unnecessary re-renders. Use useRef instead.
  4. Skipping cleanup on component unmount: If the component unmounts while a request is in flight, the request can still attempt to update state and cause a memory leak or a React warning. Abort the controller in the cleanup function of a useEffect if applicable.

Cleanup on unmount

If you trigger the fetch inside a useEffect, return a cleanup function that aborts any pending request when the component unmounts.

useEffect(() => {

  controllerRef.current = new AbortController();


  fetchSearchResults(query);


  return () => {

    controllerRef.current.abort(); // Cancel on unmount

  };

}, [query]);

Key Takeaways

  • Debounce: Delays API calls. Does not cancel in-flight requests.
  • AbortController: Cancels in-flight requests. Use it alongside debounce, not instead of it.
  • useRef: Persists the controller across renders without causing re-renders.
  • ERR_CANCELED: Axios error code for aborted requests. Handle it separately — it is not a real error.
  • Unmount cleanup: Abort pending requests in useEffect cleanup to avoid memory leaks.

If you need help implementing this pattern in a production React application, Opcito’s experts are available to assist you.

Subscribe to our feed

select webform