Using Axios Interceptors for Global Error Handling

Loading

When building applications that make HTTP requests, handling errors gracefully is crucial. Axios, a popular HTTP client for JavaScript, provides interceptors that allow you to handle HTTP request and response globally. This feature is particularly useful for handling errors in a consistent way across your application.

With Axios interceptors, you can capture any error that occurs during an API request and apply custom logic such as displaying error messages, logging errors, or retrying requests.

Here’s how to set up global error handling using Axios interceptors in a React application.


1. Understanding Axios Interceptors

Axios interceptors allow you to intercept requests and responses before they are handled by then or catch. You can use interceptors to perform actions like adding authorization tokens, logging, or handling errors in a centralized manner.

  • Request Interceptor: Intercepts outgoing requests.
  • Response Interceptor: Intercepts responses before they are passed to then or catch.
  • Error Interceptor: Catches errors in both requests and responses.

2. Setting Up Axios Instance

The first step in using interceptors is to create an Axios instance. This allows you to configure Axios with default settings, including the base URL, headers, and interceptors.

Creating an Axios Instance:

import axios from 'axios';

// Create an Axios instance with default settings
const axiosInstance = axios.create({
  baseURL: 'https://api.example.com/',  // Replace with your API URL
  timeout: 5000, // Timeout after 5 seconds
});

export default axiosInstance;

3. Adding Interceptors for Error Handling

Now that you have your Axios instance, you can add interceptors to handle errors globally.

a) Request Interceptor:

You can add logic here to add authorization tokens or modify requests before they are sent.

axiosInstance.interceptors.request.use(
  (config) => {
    // Add authorization token if available
    const token = localStorage.getItem('jwtToken');
    if (token) {
      config.headers['Authorization'] = `Bearer ${token}`;
    }
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

b) Response Interceptor:

In the response interceptor, you can handle global error responses, such as 401 Unauthorized or 500 Internal Server Error, and take actions like showing a toast or redirecting the user to a login page.

axiosInstance.interceptors.response.use(
  (response) => {
    // If the response is successful, return it
    return response;
  },
  (error) => {
    // Handle global errors here
    if (error.response) {
      // Server responded with a status other than 2xx
      if (error.response.status === 401) {
        // Handle unauthorized error (e.g., redirect to login page)
        alert('You are not authorized. Please log in again.');
        // Optionally, you could clear the token and redirect to login
        localStorage.removeItem('jwtToken');
        window.location.href = '/login';
      } else if (error.response.status === 500) {
        // Handle server errors
        alert('Server error. Please try again later.');
      } else {
        // Handle other errors
        alert(`Error: ${error.response.status}`);
      }
    } else if (error.request) {
      // The request was made but no response was received
      alert('No response from the server. Please check your connection.');
    } else {
      // Something went wrong while setting up the request
      alert(`Error: ${error.message}`);
    }
    
    return Promise.reject(error);
  }
);

4. Using Axios Interceptors in React

Now that the Axios instance is set up with interceptors, you can use it throughout your React components. This approach ensures that all API calls made using this instance will follow the global error handling rules.

Example Component Using Axios Instance:

import React, { useEffect, useState } from 'react';
import axiosInstance from './axiosInstance';

const FetchData = () => {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    // Fetch data using Axios instance
    const fetchData = async () => {
      try {
        const response = await axiosInstance.get('/data'); // Adjust API endpoint
        setData(response.data);
      } catch (error) {
        console.error('Error fetching data:', error);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, []);

  if (loading) return <div>Loading...</div>;
  if (!data) return <div>No data available</div>;

  return (
    <div>
      <h1>Fetched Data</h1>
      <pre>{JSON.stringify(data, null, 2)}</pre>
    </div>
  );
};

export default FetchData;

In this example, when you make a GET request to /data, any error occurring will trigger the response interceptor, where you can handle errors globally (e.g., show alerts, log out the user, etc.).


5. Customizing the Error Handling Based on Status Codes

Axios interceptors allow you to handle different HTTP status codes and respond accordingly. Some common status codes to consider are:

  • 401 Unauthorized: Indicates the user is not authenticated.
  • 403 Forbidden: The user doesn’t have permission to access the resource.
  • 404 Not Found: The requested resource doesn’t exist.
  • 500 Internal Server Error: Server-side error occurred.

You can customize your error handling logic by checking the status code in the response interceptor.

Example:

axiosInstance.interceptors.response.use(
  (response) => {
    return response;
  },
  (error) => {
    if (error.response) {
      const { status } = error.response;
      if (status === 401) {
        alert('Unauthorized! Please log in again.');
        // Redirect or handle logout
      } else if (status === 404) {
        alert('Resource not found.');
      } else if (status === 500) {
        alert('Server error. Please try again later.');
      }
    }
    return Promise.reject(error);
  }
);

6. Global Error Display (Optional)

You may want to display a global error message to users, for example using a global error boundary, or with UI components like Toast notifications. This can be done within the interceptor when a certain error occurs.

Example using react-toastify for global error messages:

import { toast } from 'react-toastify';

axiosInstance.interceptors.response.use(
  (response) => response,
  (error) => {
    if (error.response) {
      if (error.response.status === 500) {
        toast.error('Server error, please try again later.');
      } else {
        toast.error(`Error: ${error.response.status}`);
      }
    } else if (error.request) {
      toast.error('No response from the server.');
    } else {
      toast.error(`Error: ${error.message}`);
    }
    return Promise.reject(error);
  }
);

Leave a Reply

Your email address will not be published. Required fields are marked *