Axios

Master Axios in React — the most popular HTTP client library. Learn instance configuration, interceptors, error handling, and the patterns senior engineers use in enterprise applications.

Last reviewed: January 2025

·React 16+React 18Axios 1.x
✅
Quick Understanding: Axios is an HTTP client library that improves on the Fetch API: it throws on HTTP errors automatically, parses JSON automatically, supports request/response interceptors, and has better TypeScript support. In enterprise apps, you create a configured Axios instance with base URL, auth headers, and interceptors, then use that instance everywhere.

🔍 What Is It?

Axios is a Promise-based HTTP client with a cleaner API than fetch:

const { data } = await axios.get<User[]>('/users');
// data is already parsed JSON, typed as User[]
// throws automatically on 4xx/5xx responses

Key advantages over fetch:

  • →Throws on HTTP errors — no manual response.ok check needed
  • →Auto JSON parsing — no response.json() call needed
  • →Interceptors — middleware for requests and responses (auth, error handling, logging)
  • →Request cancellation — CancelToken (or AbortController in Axios 1.x+)
  • →Request/response transformation — transform data before sending or after receiving
  • →Better TypeScript — generic types on all methods

🎯 Why Do We Need It?

In enterprise apps, every API call needs: auth headers, error parsing, request logging, token refresh on 401, and consistent error formatting. Implementing this with raw fetch requires wrapping every call. Axios interceptors let you implement this once for all calls.

🏗️ What Happens in Real Projects?

In every enterprise React app:

  • →A configured Axios instance with base URL and default headers
  • →A request interceptor that adds the auth token
  • →A response interceptor that handles 401 (token refresh), 403 (redirect to forbidden page), and 500 (show error toast)
  • →TypeScript-typed API functions that use the instance

⚙️ How It Works

Axios instance:

Create a configured instance with axios.create(). All calls through the instance use the shared configuration.

Interceptors:

  • →Request interceptors run before every request (add auth header)
  • →Response interceptors run after every response (handle errors, refresh tokens)

Error handling:

Axios throws an AxiosError on HTTP errors. Check error.response.status for the HTTP status code and error.response.data for the error body.

💻 Example

Enterprise Axios Setup — Configured instance with auth interceptors and typed API functions.

tsx
import axios, { AxiosError } from 'axios';

// Create a configured instance
export const apiClient = axios.create({
  baseURL: import.meta.env.VITE_API_URL,
  timeout: 30_000,
  headers: { 'Content-Type': 'application/json' },
});

// Request interceptor — add auth token to every request
apiClient.interceptors.request.use((config) => {
  const token = useAuthStore.getState().token; // Zustand store
  if (token) config.headers.Authorization = `Bearer ${token}`;
  return config;
});

// Response interceptor — handle common errors globally
apiClient.interceptors.response.use(
  (response) => response, // pass through successful responses
  async (error: AxiosError<ApiError>) => {
    const status = error.response?.status;

    if (status === 401) {
      // Try to refresh the token
      try {
        await refreshToken();
        // Retry the original request
        return apiClient.request(error.config!);
      } catch {
        useAuthStore.getState().logout();
        window.location.href = '/login';
      }
    }

    if (status === 403) {
      window.location.href = '/403';
    }

    if (status === 500) {
      useToastStore.getState().showToast('Server error. Please try again.', 'error');
    }

    return Promise.reject(error);
  }
);

🤔 Common Confusions

❓ Does Axios throw on 404?

Yes — unlike fetch. Axios throws an AxiosError for any response with a status outside 2xx. This means you do not need to manually check response.ok. Catch the error and check error.response?.status for the HTTP status code.

❓ Should I use Axios or fetch in 2024?

Both are valid. fetch is built-in (no dependency). Axios is better for enterprise apps that need interceptors, consistent error handling, and request transformation. If you are using React Query, the HTTP client matters less — React Query handles the state management layer. Use whichever your team prefers.

🚨 Common Production Issues

**CORS errors** — Axios surfaces CORS errors as network errors (no response). Configure your API server to allow your frontend origin, or use a proxy in development.

**Token refresh race condition** — Multiple requests fail with 401 simultaneously, each tries to refresh the token. Fix: queue failed requests while refreshing and retry them all after one successful refresh.

**Large file uploads** — Uploading large files without progress tracking frustrates users. Use onUploadProgress in the Axios config for progress indicators.

✅ Best Practices

Create one Axios instance per API (not per component)

Handle auth, logging, and common errors in interceptors — not in each API call

Co-locate API functions in feature-specific api/ files

Use TypeScript generics for typed responses: axios.get<User[]>()

Use React Query on top of Axios for caching and state management

Test API functions by mocking the Axios instance with axios-mock-adapter

🏛️ Architect's Note

Senior Architect's Perspective

The Axios instance is the foundation of your API layer. Define it once, configure interceptors for cross-cutting concerns (auth, error handling, logging), and export typed API functions that use it. Components should never call apiClient directly — they call typed functions from the API layer. This separation makes it easy to mock in tests, swap the HTTP client, and add new cross-cutting concerns without touching component code.

💬 Frequently Asked Questions

How do I cancel an Axios request?

Axios 1.x supports AbortController (same as fetch): const controller = new AbortController(); axios.get(url, { signal: controller.signal }); controller.abort(). Use this in useEffect cleanup to cancel requests when the component unmounts or dependencies change.

🎯 Key Takeaways

1Axios throws on HTTP errors automatically — no manual response.ok check
2Create a configured instance with axios.create() — one per API
3Interceptors handle cross-cutting concerns: auth, error handling, logging
4Use typed API functions in feature-specific files — not raw axios calls in components
5Combine with React Query for caching and state management

🎯 Practice this topic in interviews

↗ Where this topic fits

Sources

Sources / References

Use these React references to verify the concept in official docs and continue into the most relevant SplashRide pages.

Related SplashRide pages

SplashRide React learning path

Browse the full React topic collection and learning order on SplashRide.

React Interview Prep

Practice React interview questions and scenario-based answers.

Frontend Engineer Career Path

A beginner-friendly journey through web foundations, React, production frontend engineering, and interview preparation.

Python Developer Career Path

A practical route through Python fundamentals, automation, backend basics, testing, projects, interview preparation, and career growth.

Fetch API

Master data fetching in React with the Fetch API. Learn patterns for loading states, error handling, cancellation, and the production patterns senior engineers use.

useEffect

Master useEffect — the hook for synchronising React components with the outside world. Learn the dependency array, cleanup functions, and how to avoid the most common production bugs.