A Guide to Using Axios for Data Fetching in Next.js
Table of contents
Introduction
In web development, fetching data from APIs is crucial. Whether you’re building client-side applications or server-side services, interacting with external APIs is essential for real-time data. One of the most popular libraries for making HTTP requests in JavaScript is Axios.
Axios is a promise-based HTTP client for JavaScript, widely used in frameworks like React, Vue, Angular, and Node.js. This article will explore Axios's features, explain why it is superior to the native fetch()
API, and provide practical examples of how to use it effectively.
What is Axios?
Axios is an open-source library for making HTTP requests from a browser or Node.js. It has a simple API to work with RESTful APIs and can handle GET, POST, PUT, DELETE, and other requests. It works well with modern JavaScript apps, managing requests asynchronously with an easy-to-use interface.
Axios is known for its built-in features, like automatic JSON handling, request cancellation, and more powerful configuration options compared to the native fetch()
API.
Key Features of Axios
Axios provides several essential features that make it highly favored by developers:
Promise-Based: Axios uses JavaScript promises, making it easier to write and handle asynchronous code by managing requests, responses, and errors with
.then()
and.catch()
syntax.Automatic JSON Parsing: Unlike the native
fetch()
method, Axios automatically parses JSON data for both requests and responses, reducing the amount of code developers need to write.Request Interceptors: Axios allows developers to intercept requests or responses before they are processed. This is useful for adding authentication tokens, changing request headers, or logging activities.
Timeouts: Axios supports setting timeouts for requests, which helps prevent hanging connections and gives better control over the application's flow.
Request and Response Transformation: Axios lets you modify requests and responses before they are sent or received, providing flexibility when working with different API specifications.
Error Handling: Axios provides built-in error handling that can capture and process network errors, making it easier to manage failed requests in applications.
Cancellation: Axios allows you to cancel requests using
CancelToken
, which is especially helpful for handling slow or unnecessary API calls.Browser and Node.js Compatibility: Axios is built to work in both client-side and server-side environments. This flexibility makes it perfect for full-stack JavaScript applications.
Axios vs. Native fetch()
When comparing Axios to the native fetch()
method, Axios offers several advantages that can simplify development and improve your application's performance.
Axios is great for situations that need more customization, better error handling, and automatic data transformation. It also makes coding easier by handling common tasks like timeouts and request cancellations.
Installing Axios
To use Axios in a project, you first need to install it. If you're using npm or Yarn for managing dependencies, installation is straightforward:
Using npm:
npm install axios
Using Yarn:
yarn add axios
After installation, you can import Axios into your JavaScript or TypeScript file:
import axios from 'axios';
Using Axios: We built small app
To structure your project with Axios requests in separate files, you can organize it like this:
Final File Structure:
bashCopy code/src
/api
eraApi.ts # Axios API requests for Eras
/components
EraList.tsx # Component for listing, deleting, and editing Eras
EraForm.tsx # Form component for creating or updating an Era
App.tsx # Main app component combining all components
/styles
App.css # Basic CSS styling
Step 1: Create the API file
/src/api/eraApi.ts
This file will handle the API calls using Axios for CRUD operations.
// /src/api/eraApi.ts
import axios from 'axios';
export interface Era {
_id: string;
name: string;
description: string;
image_url: string;
}
// Fetch all Eras
export const fetchEras = async (): Promise<Era[]> => {
try {
const { data } = await axios.get('/api/eras');
return data;
} catch (error) {
console.error('Error fetching eras:', error);
throw new Error('Failed to fetch eras');
}
};
// Create a new Era
export const createEra = async (eraData: { name: string; description: string; image_url: string }): Promise<void> => {
try {
await axios.post('/api/eras', eraData);
} catch (error) {
console.error('Error creating era:', error);
throw new Error('Failed to create era');
}
};
// Update an Era
export const updateEra = async (id: string, updatedEraData: { name?: string; description?: string; image_url?: string }): Promise<void> => {
try {
await axios.put(`/api/eras/${id}`, updatedEraData);
} catch (error) {
console.error('Error updating era:', error);
throw new Error('Failed to update era');
}
};
// Delete an Era
export const deleteEra = async (id: string): Promise<void> => {
try {
await axios.delete(`/api/eras/${id}`);
} catch (error) {
console.error('Error deleting era:', error);
throw new Error('Failed to delete era');
}
};
Step 2: Create the Form Component
/src/components/EraForm.tsx
This component will handle the form for creating or editing an Era
.
// /src/components/EraForm.tsx
import React, { useState } from 'react';
import { createEra, updateEra, Era } from '../api/eraApi';
interface EraFormProps {
existingEra?: Era; // If provided, the form will be in "edit" mode
onSuccess: () => void; // Callback to refresh the list on success
}
const EraForm: React.FC<EraFormProps> = ({ existingEra, onSuccess }) => {
const [name, setName] = useState(existingEra?.name || '');
const [description, setDescription] = useState(existingEra?.description || '');
const [image_url, setImageUrl] = useState(existingEra?.image_url || '');
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
try {
if (existingEra) {
// Edit existing era
await updateEra(existingEra._id, { name, description, image_url });
} else {
// Create new era
await createEra({ name, description, image_url });
}
onSuccess(); // Call the success callback to refresh the list
} catch (error) {
console.error('Failed to submit form:', error);
}
};
return (
<form onSubmit={handleSubmit}>
<div>
<label>Name:</label>
<input value={name} onChange={(e) => setName(e.target.value)} />
</div>
<div>
<label>Description:</label>
<input value={description} onChange={(e) => setDescription(e.target.value)} />
</div>
<div>
<label>Image URL:</label>
<input value={image_url} onChange={(e) => setImageUrl(e.target.value)} />
</div>
<button type="submit">{existingEra ? 'Update Era' : 'Create Era'}</button>
</form>
);
};
export default EraForm;
Step 3: Create the List Component
/src/components/EraList.tsx
This component will display the list of eras and handle delete operations.
// /src/components/EraList.tsx
import React from 'react';
import { Era, deleteEra } from '../api/eraApi';
interface EraListProps {
eras: Era[];
onDeleteSuccess: () => void;
onEdit: (era: Era) => void; // Callback to handle editing
}
const EraList: React.FC<EraListProps> = ({ eras, onDeleteSuccess, onEdit }) => {
const handleDelete = async (id: string) => {
try {
await deleteEra(id);
onDeleteSuccess(); // Refresh list on success
} catch (error) {
console.error('Failed to delete era:', error);
}
};
return (
<ul>
{eras.map((era) => (
<li key={era._id}>
<h3>{era.name}</h3>
<p>{era.description}</p>
<img src={era.image_url} alt={era.name} width="100" />
<button onClick={() => onEdit(era)}>Edit</button>
<button onClick={() => handleDelete(era._id)}>Delete</button>
</li>
))}
</ul>
);
};
export default EraList;
Step 4: Create the Main App Component
/src/components/App.tsx
This is the main app component that ties everything together.
// /src/components/App.tsx
import React, { useEffect, useState } from 'react';
import { fetchEras, Era } from '../api/eraApi';
import EraForm from './EraForm';
import EraList from './EraList';
import '../styles/App.css';
const App: React.FC = () => {
const [eras, setEras] = useState<Era[]>([]);
const [editingEra, setEditingEra] = useState<Era | null>(null);
const loadEras = async () => {
try {
const data = await fetchEras();
setEras(data);
} catch (error) {
console.error('Failed to load eras:', error);
}
};
useEffect(() => {
loadEras(); // Load eras when the component mounts
}, []);
return (
<div className="App">
<h1>Era Manager</h1>
{/* Era Form (for creating or editing) */}
<EraForm
existingEra={editingEra}
onSuccess={() => {
loadEras(); // Refresh list on success
setEditingEra(null); // Clear editing form
}}
/>
{/* Era List */}
<EraList
eras={eras}
onDeleteSuccess={loadEras} // Refresh list on delete success
onEdit={(era) => setEditingEra(era)} // Handle editing
/>
</div>
);
};
export default App;
Step 5: Add Basic Styles
/src/styles/App.css
This file will contain some basic styles to make the app look clean.
/* /src/styles/App.css */
.App {
font-family: Arial, sans-serif;
padding: 20px;
}
h1 {
color: #333;
}
form {
margin-bottom: 20px;
}
input {
margin: 5px;
padding: 5px;
width: 200px;
}
button {
margin: 5px;
padding: 5px 10px;
}
ul {
list-style-type: none;
padding: 0;
}
li {
margin: 10px 0;
border-bottom: 1px solid #ccc;
padding-bottom: 10px;
}
Running the App
Run the App: If using a tool like
create-react-app
, simply run:npm run dev // If you using next js
This small app will now allow you to:
Fetch and display a list of
Eras
Create a new
Era
Update an existing
Era
Delete an
Era
Some more important data-fetching libraries include:
React Query (40.4k ⭐) — A library handles fetching, caching, background updates and stale data out of the box with zero-configuration. It is backend agnostic so you can use React Query with literally any asynchronous data fetching client.
SWR (29.7k ⭐) — A React Hooks library for data fetching, created by Next.js team, lightweight, and backend agnostic.
Apollo Client (19.3k ⭐) — A comprehensive state management library for JavaScript that enables you to manage both local and remote data with GraphQL. Use it to fetch, cache, and modify application data, all while automatically updating your UI.
Relay (18.2k ⭐) — The production-ready GraphQL client for React, developed by Facebook, was designed to be performant from the ground up, built upon locally declaring data dependencies for components.
RTK Query (10.5k ⭐) — An optional addon included in the Redux Toolkit package, and its functionality is built on top of the other APIs in Redux Toolkit.
urql (8.5k ⭐) — A highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.
Wretch (4.5k ⭐) — A small wrapper around Fetch API designed to simplify the way to perform network requests and handle responses. It’s strongly typed, written in TypeScript, compatible with modern browsers, Node.js 14+ and Deno.
Data Fetching
Web applications often need to get data from a server to show it. They also need to update this data, send updates back to the server, and keep the cached data on the client in sync with the server. This gets more complicated because modern apps need to:
Track loading state to show spinners in the UI
Avoid making duplicate requests for the same data
Use optimistic updates to make the UI feel faster
Manage cache lifetimes as the user interacts with the UI
Common features
React data fetching libraries provide convenient abstractions and utilities to handle data fetching and management in React applications. While the specific features can vary between libraries, here are some common features found in many React data fetching libraries:
Transport and protocol agnostic (REST, GraphQL, etc)
Caching, refetching, polling, realtime
Pagination, load more, infinite scrolling
Requests and responses interception
Revalidation on focus, network recovery
Performance optimizations
Request cancellation
In this article, we explore Axios, a popular promise-based HTTP client for JavaScript, frequently used in frameworks like React, Vue, Angular, and Node.js. We'll cover its key features, compare it with the native fetch() API, and provide a step-by-step guide on building a small application using Axios for CRUD operations. Additionally, we touch on other notable data-fetching libraries like React Query, SWR, Apollo Client, Relay, RTK Query, urql, and Wretch, discussing their common features and use cases in modern web development.
Conclusion:
In conclusion, Axios is a versatile HTTP client that simplifies data fetching in web applications. Its promise-based architecture, automatic JSON parsing, and extensive configuration options make it superior to the native fetch()
API. By following this guide, you can effectively integrate Axios into your Next.js projects for CRUD operations. Additionally, other data-fetching libraries like React Query, SWR, and Apollo Client offer unique features that may better suit specific needs, helping you optimize data management in your applications.
Subscribe to my newsletter
Read articles from Ramkumar Raghuwanshi directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Ramkumar Raghuwanshi
Ramkumar Raghuwanshi
Computer Science Engineering student with a keen interest in software development and technology. Skilled in coding, problem-solving, and web development, I’m passionate about turning ideas into real-world solutions. Always eager to learn and grow in the tech industry