Code-Along 1 - API Error Handling
Introduction to API Error Handling
Why Error Handling Matters
Error handling is a critical part of any application that interacts with external APIs. Well-implemented error handling:
- Improves user experience by providing meaningful feedback
- Prevents application crashes
- Makes debugging easier
- Increases application reliability
When working with APIs, a number of things can go wrong: network issues, server problems, invalid requests, authentication failures, etc. Properly handling these errors ensures your application remains functional and user-friendly even when things don't go as expected.
HTTP Status Codes
Understanding HTTP Status Codes
HTTP status codes are standardized responses from servers that indicate the outcome of an HTTP request. They are grouped into five classes:
- 1xx (Informational): Request received, continuing process
- 2xx (Success): Request successfully received, understood, and accepted
- 3xx (Redirection): Further action needs to be taken to complete the request
- 4xx (Client Error): Request contains bad syntax or cannot be fulfilled
- 5xx (Server Error): Server failed to fulfill a valid request
// Common HTTP Status Codes
200 - OK // Request succeeded
201 - Created // Resource created successfully
400 - Bad Request // Server couldn't understand the request
401 - Unauthorized // Authentication required
403 - Forbidden // Server understood but refuses to authorize
404 - Not Found // Resource not found
500 - Internal Server Error // Server encountered an unexpected condition
Error Handling in React
Implementing Error Handling with Fetch API
When working with the Fetch API in React, it's important to understand that fetch doesn't automatically reject on HTTP error statuses. You need to check if the response is ok (status in 200-299 range) and throw an error manually if needed.
Best practices for error handling with fetch:
- Use try/catch blocks to capture both network errors and your thrown HTTP errors
- Track loading states to provide feedback to users
- Store error information in state to display to users
- Consider different types of errors and handle them appropriately
// Complete Error Handling Example
import { useState, useEffect } from 'react';
function DataFetcher() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
setLoading(true);
setError(null);
try {
const response = await fetch('https://api.example.com/data');
// Check for HTTP errors
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
// Parse the JSON
const result = await response.json();
setData(result);
} catch (err) {
setError(err.message || 'Something went wrong');
console.error('Error fetching data:', err);
} finally {
setLoading(false);
}
};
fetchData();
}, []);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
if (!data) return <div>No data available</div>;
return (
<div>
<h2>Data Loaded Successfully</h2>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}
Advanced Error Handling with Axios
Using Axios for API Requests
Axios is a popular alternative to the Fetch API that provides some additional features and more intuitive error handling. Unlike fetch, Axios automatically throws errors for non-2xx status codes.
- Automatically parses JSON responses
- Throws errors for HTTP error status codes
- Provides more detailed error information
- Supports request and response interceptors
// Axios Error Handling Example
import { useState, useEffect } from 'react';
import axios from 'axios';
function AxiosDataFetcher() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
setLoading(true);
setError(null);
try {
const response = await axios.get('https://api.example.com/data');
setData(response.data);
} catch (err) {
// Axios provides more detailed error information
if (err.response) {
// The request was made and the server responded with a status code
// that falls out of the range of 2xx
console.error('Error data:', err.response.data);
console.error('Error status:', err.response.status);
setError(`Server error: ${err.response.status}`);
} else if (err.request) {
// The request was made but no response was received
console.error('Error request:', err.request);
setError('No response from server');
} else {
// Something happened in setting up the request
console.error('Error message:', err.message);
setError('Request configuration error');
}
} finally {
setLoading(false);
}
};
fetchData();
}, []);
// Render UI based on state
// ...
}
User Feedback and Error UI
Designing Effective Error Messages
Good error handling isn't just about catching errors; it's also about presenting them to users in a way that is:
- Clear: Use plain language that explains what went wrong
- Helpful: Provide guidance on what to do next
- Context-appropriate: Different errors may need different levels of detail
- Actionable: When possible, offer a way to resolve the issue
// Error UI Component Example
function ErrorDisplay({ error, retry }) {
// Different UI based on error type
if (error.includes('network') || error.includes('offline')) {
return (
<div className="error-container network-error">
<h3>Connection Problem</h3>
<p>Please check your internet connection and try again.</p>
<button onClick={retry}>Retry</button>
</div>
);
}
if (error.includes('401') || error.includes('403')) {
return (
<div className="error-container auth-error">
<h3>Authentication Error</h3>
<p>You don't have permission to access this resource.</p>
<button onClick={() => window.location.href = '/login'}>Log In</button>
</div>
);
}
// Default error display
return (
<div className="error-container">
<h3>Something Went Wrong</h3>
<p>{error}</p>
<button onClick={retry}>Try Again</button>
</div>
);
}
Project: Implementing Error Handling
Let's apply what we've learned by building a weather app that demonstrates robust error handling.
Project Repository Weather API Documentation