What is Axios Interceptors in React

This article explains what Axios interceptors are and how to use them in a React application. You will learn how interceptors act as middleware for your HTTP requests and responses, allowing you to globally manage authentication tokens, handle API errors, and log data without duplicating code across your components.

Understanding Axios Interceptors

Axios interceptors are functions that Axios calls automatically before a request is sent to the server, or before a response is passed to the .then() or .catch() blocks in your application code.

Think of them as a toll booth or middleware for your network requests. Instead of manually adding authorization headers or error-handling logic to every single API call in your React components, you can define these rules once globally.

There are two main types of interceptors: 1. Request Interceptors: Triggered right before an HTTP request leaves your application. 2. Response Interceptors: Triggered as soon as a response arrives from the server, but before your application code processes it.

Common Use Cases in React

How to Implement Interceptors in React

To implement interceptors cleanly, it is best practice to create a dedicated Axios instance. This prevents pollution of the global Axios object and allows you to configure different behavior for different APIs.

Here is a practical example of setting up a request and response interceptor:

import axios from 'axios';

// 1. Create an Axios instance
const apiClient = axios.create({
  baseURL: 'https://api.example.com',
  headers: {
    'Content-Type': 'application/json',
  },
});

// 2. Add a Request Interceptor
apiClient.interceptors.request.use(
  (config) => {
    // Retrieve the token (e.g., from localStorage)
    const token = localStorage.getItem('userToken');
    
    // If the token exists, inject it into the headers
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    
    return config;
  },
  (error) => {
    // Handle request errors
    return Promise.reject(error);
  }
);

// 3. Add a Response Interceptor
apiClient.interceptors.response.use(
  (response) => {
    // Any status code within the range of 2xx triggers this function
    return response;
  },
  (error) => {
    // Any status codes outside the range of 2xx trigger this function
    if (error.response && error.response.status === 401) {
      // Handle unauthorized errors (e.g., redirect to login, clear storage)
      console.warn('Unauthorized! Redirecting to login...');
      localStorage.removeItem('userToken');
      window.location.href = '/login';
    }
    
    return Promise.reject(error);
  }
);

export default apiClient;

Managing Interceptors in React Lifecycles

In some advanced React applications, you may want to attach interceptors inside a React hook or component to access state (like a Redux store or React Context).

If you register interceptors inside a component or custom hook, you must eject (remove) them when the component unmounts to prevent memory leaks and duplicate interceptor executions.

import { useEffect } from 'react';
import apiClient from './apiClient';

function App() {
  useEffect(() => {
    const myInterceptor = apiClient.interceptors.request.use(config => {
      // Modify config
      return config;
    });

    // Clean up the interceptor when the component unmounts
    return () => {
      apiClient.interceptors.request.eject(myInterceptor);
    };
  }, []);

  return <div>My React App</div>;
}

Using Axios interceptors keeps your React components clean, dry (Don’t Repeat Yourself), and focused solely on rendering UI rather than managing low-level API configurations.