Consuming APIs: Fetch, Axios & Error Handling
Overview
Modern web applications are built around APIs. This tutorial covers the
essential skills for consuming APIs from the browser: understanding RESTful
and GraphQL APIs, using the native Fetch API, the
Axios library, handling errors gracefully, managing loading
states, and cancelling requests with AbortController.
1. REST vs GraphQL
REST (Representational State Transfer)
- Resources: Each endpoint represents a resource (
/users,/posts/1). - HTTP methods: GET (read), POST (create), PUT/PATCH (update), DELETE.
- Stateless: Each request contains all needed information.
- Advantages: Caching, standardised, widely understood.
- Disadvantages: Over‑fetching (getting more data than needed) and under‑fetching (needing multiple endpoints).
GraphQL
- Single endpoint: All queries go to
/graphql. - Client‑specified queries: The client asks for exactly the fields it needs.
- Strong typing: Schema defines available types and queries.
- Advantages: No over‑/under‑fetching, multiple resources in one request.
- Disadvantages: Complexity, caching is harder, learning curve.
2. The Fetch API
fetch() is the native browser API for making HTTP requests.
It returns a Promise that resolves to a Response object.
GET request
POST request
fetch does not reject on HTTP error
status (e.g., 404, 500). You must check response.ok and throw manually.
3. Axios
Axios is a popular HTTP client that works in both browsers and Node.js. It provides a cleaner API, automatic JSON transformation, and better error handling.
Installation
GET request
POST request
Advantages of Axios over Fetch
- Throws errors on HTTP error status (4xx, 5xx).
- Automatic JSON parsing.
- Request/response interceptors.
- Timeouts and cancellation built‑in (though Fetch has AbortController).
4. Error Handling
Robust applications handle errors gracefully. Common strategies:
- Network errors: No internet, DNS failure, CORS issues.
- HTTP errors: 404 (Not Found), 401 (Unauthorized), 500 (Server Error).
- Business logic errors: Validation failures, duplicates, insufficient funds.
5. Loading States & Request Cancellation
Loading UI
Show a spinner or skeleton while the request is in flight. This improves perceived performance and user experience.
Request Cancellation (AbortController)
Cancel in‑flight requests when a component unmounts or when dependencies change, to prevent memory leaks and race conditions.
Quiz
Question 1
In a RESTful API, which HTTP method is typically used to create a new resource?
- GET
- POST
- PUT
- DELETE
Show answer
Question 2
Does the fetch API throw an error for a 404 response?
- Yes, always
- No, you must check
response.ok - Only if the request fails
- Depends on the browser
Show answer
response.ok.Question 3
Which method is used to cancel an in‑flight fetch request?
- cancel()
- abort()
- stop()
- clear()
Show answer
abort() via AbortController.Exercises
Exercise 1
Write a function fetchUser(id) that uses fetch to
get a user from /api/users/{id} and returns the parsed JSON. Handle errors by
throwing a custom error message if the response is not OK.
Sample answer
async function fetchUser(id) {
const response = await fetch(`/api/users/${id}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
}
Exercise 2
Convert the fetchUser function to use Axios instead. What
differences do you notice?
Sample answer
import axios from 'axios';
async function fetchUser(id) {
try {
const response = await axios.get(`/api/users/${id}`);
return response.data;
} catch (error) {
throw new Error(`Axios error: ${error.message}`);
}
}
Differences: Axios throws on HTTP errors, so we don't need to check
response.ok; the data is in response.data, not
response.json().
Homework
Homework 1
Build a React component UserProfile that fetches a user by ID
from /api/users/:id using Axios. It should show a loading spinner while
fetching, display the user data when loaded, and show an error message if the request fails.
Also cancel the request if the component unmounts.
Sample answer
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const controller = new AbortController();
setLoading(true);
setError(null);
axios.get(`/api/users/${userId}`, { signal: controller.signal })
.then(res => setUser(res.data))
.catch(err => {
if (!axios.isCancel(err)) setError(err.message);
})
.finally(() => setLoading(false));
return () => controller.abort();
}, [userId]);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
return <div>{user.name} - {user.email}</div>;
}
Mini‑Project
Weather Dashboard
Build a React application that fetches weather data from a public API (e.g., OpenWeatherMap).
- Input field for city name.
- On submit, fetch weather data (temperature, humidity, condition).
- Display the data in a styled card.
- Show loading and error states.
- Cancel the request if the user submits a new city before the previous request completes.
Sample implementation
Component structure:
function WeatherApp() {
const [city, setCity] = useState('');
const [weather, setWeather] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const controllerRef = useRef(null);
const fetchWeather = async (cityName) => {
if (controllerRef.current) controllerRef.current.abort();
const controller = new AbortController();
controllerRef.current = controller;
setLoading(true);
setError(null);
try {
const res = await axios.get(`https://api.openweathermap.org/data/2.5/weather?q=${cityName}&appid=YOUR_API_KEY`, { signal: controller.signal });
setWeather(res.data);
} catch (err) {
if (!axios.isCancel(err)) setError(err.message);
} finally {
setLoading(false);
}
};
const handleSubmit = (e) => {
e.preventDefault();
if (city.trim()) fetchWeather(city);
};
return ( ... );
}
Tutorial Summary
You learned how to communicate with APIs from a React application. We covered the differences between REST and GraphQL, the native Fetch API, the Axios library, robust error handling, loading states, and request cancellation. The exercises and mini‑project gave you practical experience in building resilient data‑fetching components.
Key takeaway: Always handle loading, error, and success states. Use modern tools like Axios and AbortController to keep your data‑fetching code clean and reliable.