Skip to Content

Axios Guide — What It Is, How It Works, and How to Build a Wrapper

Overview — What Is Axios?

Axios is a popular JavaScript HTTP client used to send API requests from the browser or Node.js. It provides a friendlier API than the native fetch(), with additional features:

  • Automatic JSON transformation
  • Request & response interceptors
  • Automatic timeout handling
  • Query params handling
  • Request cancellation
  • Global config support
  • Error handling with rich error objects

Why Use Axios Instead of fetch()?

FeatureFetchAxios
Auto JSON parsing
Auto error handling❌ must manually check status✅ throws on non-2xx
Interceptors
Timeout handling❌ needs AbortController✅ built-in
Upload progress tracking
Simpler params handling
Easy global defaults
Request cancellation⚠️ possible but complex✅ easy

In short: Axios → cleaner code, simpler error handling, easier token logic, better DX.


Basic Axios Usage

GET request

import axios from "axios"; const res = await axios.get("/api/users"); console.log(res.data);

POST request

const res = await axios.post("/api/login", { email: "alice@mail.com", password: "123456", });

Send query params

axios.get("/api/products", { params: { page: 2, sort: "newest" }, });

Setting global defaults

axios.defaults.baseURL = "https://api.example.com"; axios.defaults.headers.common["Authorization"] = "Bearer token";

Why Create an Axios Wrapper?

Using Axios directly in every component causes problems:

Repeated code everywhere

  • base URL
  • authorization token
  • error handling
  • redirect logic
  • toasts
  • headers
  • passing cookies
  • parsing FormData
  • logger
  • response normalization

A wrapper fixes all of these.

Benefits of an Axios wrapper

  • Centralized error handling
  • Auth token automatically attached
  • Redirect to login automatically
  • Consistent toasts
  • Prevent duplicate code
  • Handle FormData dynamically
  • Cookie reading in one place
  • Body/params abstraction
  • Reusable custom instance
  • Optimize URL placeholders

Creating a reusable Axios instance

const axiosInstance = axios.create({ baseURL: `${process.env.baseUrl}`, headers: { Accept: "application/json", "Content-Type": "application/json" } });

Why?

  • Avoid repeating baseURL
  • Give all requests default headers
  • Allow interceptors later
  • Makes it easier to replace backend URLs later

The Wrapper Function

export const api = async function <T = any>(url: string, options: APIOptions = { showToaster: true }): Promise<T> {

Why?

  • Universal API function for all components
  • Generic type <T> makes response typed
  • Configurable options per request

Token Attachment

// Get cookie with some package const token = 'YOUR_COOKIE'; headers: { Authorization: token ? `Bearer ${token}` : "", }

Why?

  • Automatically attaches the Authorization header
  • No need to manually pass token per request
  • Better security and consistency

Handling FormData Automatically

"Content-Type": options.body instanceof FormData ? "multipart/form-data" : "application/json",

Why?

  • Switching content type based on body
  • Useful for file uploads
  • Zero manual effort

Error Handling

if (status === 401) { // Do sometime here }

Features:

  • Auto redirect to login on 401
  • Auto clear invalid tokens
  • Auto show toast with backend message
  • Ability to disable toasts per request

Throw Error Again

throw err;

Why?

You want the component to still react:

  • show UI fallback
  • disable button
  • handle specific errors

Otherwise the wrapper would “eat” the error.


Example Usage

GET request

const user = await api("/user/profile");

POST request with body

await api("/auth/login", { method: "POST", body: { email, password } });

POST FormData

const fd = new FormData(); fd.append("file", myFile); await api("/upload", { method: "POST", body: fd });

References


Summary

  • Axios simplifies HTTP requests and improves DX compared to fetch().

  • A wrapper gives you a centralized layer for:

    • tokens
    • errors
    • toasts
    • redirects
    • dynamic URL injection
    • JSON/Multipart handling
  • The wrapper you provided is clean, scalable, and production-ready.

  • It ensures consistent behavior across the entire codebase and reduces repeated logic.