
Day 16 – Fetching Data in React (API Calls with fetch & axios)
Learn fetching data in React using fetch API and axios with async/await. Includes examples with loading and error states for beginners.
When building real-world apps, you rarely work with static data. Instead, your app will often need to fetch data from APIs — like fetching products from an e-commerce backend, posts from a blog API, or user info after login.
In React, data fetching is typically done using:
- fetch API (built into browsers), or
- axios (a popular HTTP library).
Both are often used together with the useEffect
hook, because fetching is a side effect (it happens outside React’s rendering).
In this blog, we’ll cover:
- Basics of fetching with
fetch
. - Fetching with
axios
. - Using async/await for cleaner code.
- Handling loading and error states properly.
- Best practices.
Fetching Data with fetch API
The fetch API is built into modern browsers and allows you to make HTTP requests.
Example: Fetch Users
import React, { useEffect, useState } from "react";
function UsersList() {
const [users, setUsers] = useState([]); // stores fetched data
const [loading, setLoading] = useState(true); // tracks loading state
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/users")
.then((res) => res.json()) // convert response to JSON
.then((data) => {
setUsers(data); // store data in state
setLoading(false); // stop loading
})
.catch(() => setLoading(false)); // handle network errors
}, []);
if (loading) return <p>Loading...</p>;
return (
<ul>
{users.map((user) => (
<li key={user.id}>
{user.name} – {user.email}
</li>
))}
</ul>
);
}
Explanation
useEffect
ensures fetching happens after the component mounts (not on every render).- While waiting for the API, we display “Loading…”.
- Once data arrives, we update state with
setUsers(data)
and render it. - The
.catch()
ensures our app doesn’t crash if the API fails.
Fetching Data with axios
While fetch
works fine, many developers prefer axios because:
- It automatically converts responses to JSON.
- Has cleaner error handling.
- Supports request cancellation, interceptors, etc.
Install axios
npm install axios
Example: Fetch Posts
import React, { useEffect, useState } from "react";
import axios from "axios";
function PostsList() {
const [posts, setPosts] = useState([]);
useEffect(() => {
axios
.get("https://jsonplaceholder.typicode.com/posts")
.then((res) => setPosts(res.data))
.catch((err) => console.error("Error fetching posts:", err));
}, []);
return (
<div>
<h2>Posts</h2>
<ul>
{posts.slice(0, 5).map((post) => (
<li key={post.id}>
<b>{post.title}</b>
</li>
))}
</ul>
</div>
);
}
Explanation
axios.get(url)
makes a GET request.res.data
contains the response (no need for.json()
).- We only render the first 5 posts with
.slice(0, 5)
for brevity.
Using async/await for Cleaner Code
Instead of chaining .then()
, we can use async/await for readability.
function Products() {
const [products, setProducts] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchProducts = async () => {
try {
let res = await fetch("https://fakestoreapi.com/products");
if (!res.ok) throw new Error("Failed to fetch");
let data = await res.json();
setProducts(data);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
fetchProducts();
}, []);
if (loading) return <p>Loading products...</p>;
if (error) return <p style={{ color: "red" }}>Error: {error}</p>;
return (
<ul>
{products.map((p) => (
<li key={p.id}>
{p.title} – ${p.price}
</li>
))}
</ul>
);
}
What’s Happening?
try { ... } catch { ... } finally { ... }
ensures we handle success, errors, and cleanup.- If API fails, we display an error message instead of a blank screen.
- This makes the app robust and user-friendly.
Best Practices for Fetching Data in React
- ✅ Always handle loading and error states. Never leave users guessing.
- ✅ Use
useEffect
properly with dependencies (avoid infinite loops). - ✅ Use
key
when rendering lists (from API data). - ✅ For complex apps, use React Query or SWR for advanced caching, retries, and background updates.
- ✅ Cleanup effects when fetching in components that may unmount.
Internal Links
- Learn useEffect in React since fetching data always involves side effects.
- Review Lists & Keys in React to render API data correctly.
External Links
Conclusion
Fetching data is one of the most essential skills in React. You can start with the fetch API, switch to axios for advanced needs, and always remember to handle loading and error states.
👉 Next Blog (Day 17): Async useEffect + Loading/Error States in React