DEV Community

Nilesh Kumar
Nilesh Kumar

Posted on

How to Cancel API Calls in React with Axios: A Step-by-Step Guide

Learn how to manage multiple API calls in React by canceling previous requests with Axios. This guide shows you how to use Axios’s CancelToken to cancel requests that are no longer needed. By doing this, you can improve performance and reduce unnecessary network traffic when users switch between selections, like changing stories in a React component.

In modern web apps, especially those built with React, it’s common to fetch data from APIs when users take actions, like clicking on a story or selecting a product. However, if a user triggers multiple actions quickly, previous requests might still be running in the background, using up resources and potentially showing outdated or incorrect data.

How to Cancel API Calls in React with Axios: A Step-by-Step Guide

In this post, we’ll show you how to solve this problem by canceling ongoing Axios requests whenever a user picks a new item. This helps avoid unnecessary API calls, boosts performance, and makes sure you get the most up-to-date data. Let’s go through the solution with an easy example!

Understanding the Problem:

Imagine you have a React component that loads audio for a story from an API every time a user selects a new story. But if the user quickly switches between stories, the previous API requests might still be running in the background. This can lead to extra load on the server, delays, and problems like playing the wrong audio.

To solve this, we need to cancel the previous request when a new request is triggered.

Using Axios Cancellation Tokens in React

To cancel ongoing requests, we’ll use Axios’s CancelToken. This lets us stop a request if it’s not needed anymore, like when a user picks a different story before the previous request is done. Here’s how you can set this up in a React component:

Step 1: Create a Cancellation Token

First, we need to create a reference that stores the cancellation token. We can use the useRef hook in React to persist the token across re-renders of the component.

const cancelTokenSource = useRef(null);
Enter fullscreen mode Exit fullscreen mode

Step 2: Cancel Previous Request Before Making a New One

Before we make a new API call, we check if there’s an existing request. If there is, we cancel it. We do this by calling cancel() on the current cancelTokenSource.

if (cancelTokenSource.current) {
  cancelTokenSource.current.cancel('Operation canceled due to new request.');
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Create a New Cancellation Token for Each Request

After canceling the previous request, we create a new cancel token source for the next API call.

cancelTokenSource.current = axios.CancelToken.source();
Enter fullscreen mode Exit fullscreen mode

Step 4: Make the API Request with the Cancel Token

Now, when we make the actual API request, we pass the cancel token along with the request. This ensures that the request can be canceled if needed.

const response = await axios.get(url, {
  cancelToken: cancelTokenSource.current.token,
});
Enter fullscreen mode Exit fullscreen mode

Step 5: Handle Request Cancellation

In the catch block, we handle the cancellation error separately. If the request was canceled, we log a message and do not treat it as a real error.

catch (error) {
  if (axios.isCancel(error)) {
    console.log('Request canceled:', error.message); 
  } else {
    // Handle other errors
    console.log('API call error:', error);
  }
}
Enter fullscreen mode Exit fullscreen mode

Example Code: Full React Component Implementation

Here’s the full implementation of the solution in a React component that fetches a story’s audio when the user selects a story:

import React, { useState, useEffect, useRef } from 'react';
import axios from 'axios';
import { toast } from 'react-toastify';

const StorySpeechComponent = ({ id }) => {
  const [base64audio, setBase64audio] = useState(null);
  const cancelTokenSource = useRef(null);  // Store the cancel token

  const getStorySpeech = async (id) => {
    if (cancelTokenSource.current) {
      cancelTokenSource.current.cancel('Operation canceled due to new request.');
    }

    cancelTokenSource.current = axios.CancelToken.source();

    try {
      const url = `http:/localhost:8000/api/v1/getAudio/${id}`; // update your api url here
      const response = await axios.get(url, {
        cancelToken: cancelTokenSource.current.token, // creating the canel token for the api
      });

      if (response?.data?.audio) {
        setBase64audio(response.data.audio); // save your response to any state as requre
      }
    } catch (error) {
      if (axios.isCancel(error)) {
        console.log('Request canceled:', error.message);
      } else {
        console.log('Get Story Speech API error:', error.response);
        if (error.response?.status === 400) {
          toast.error(error.response.data["non_field_errors"][0]);
        }
      }
    }
  };

  useEffect(() => {
    if (id) {
      getStorySpeech(id);
    }

    return () => {
      if (cancelTokenSource.current) {
        cancelTokenSource.current.cancel('Component unmounted or story changed.');
      }
    };
  }, [id]);  // Re-fetch when the selected story Id changes

  return (
    <div>
      <h1>Story Speech</h1>
      {base64audio ? (
        <audio controls>
          <source src={`data:audio/mp3;base64,${base64audio}`} type="audio/mp3" />
          Your browser does not support the audio element.
        </audio>
      ) : (
        <p>Loading audio...</p>
      )}
    </div>
  );
};

export default StorySpeechComponent;
Enter fullscreen mode Exit fullscreen mode

Conclusion:

By using Axios’s cancellation feature, we can avoid unnecessary network requests and keep our React app running smoothly. This is especially helpful when multiple API calls are triggered quickly, like when users are switching between different items. This simple approach boosts performance and improves the user experience by preventing race conditions and cutting down on unnecessary API calls.

Top comments (0)