API Integration – Handling Loading and Error States in React
Introduction
When a React application communicates with an API, the response is not immediate. During this time, users should see a loading indicator. If something goes wrong, they should receive a clear error message.
Handling loading and error states is essential for building reliable, user-friendly, and production-ready React applications.
Why Are Loading and Error States Important?
Without proper loading and error handling:
- Users see blank screens
- Applications feel slow or broken
- Errors become hard to debug
- User experience degrades
Proper handling ensures:
- Better user feedback
- Predictable UI behavior
- Easier debugging
- Professional application flow
Common States in API Calls
A typical API call has three states:
- Loading – Request in progress
- Success – Data received
- Error – Request failed
React applications usually manage these using state variables.
Basic Loading and Error State Setup
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
Each state serves a clear purpose:
- loading controls UI feedback
- error stores error details
- data stores API response
Example: Handling Loading and Error with Fetch API
import { useEffect, useState } from "react";
function UsersList() {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/users")
.then((response) => {
if (!response.ok) {
throw new Error("Failed to fetch data");
}
return response.json();
})
.then((data) => {
setUsers(data);
setLoading(false);
})
.catch((err) => {
setError(err.message);
setLoading(false);
});
}, []);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error}</p>;
return (
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
export default UsersList;
Example: Handling Loading and Error with Axios
import { useEffect, useState } from "react";
import axios from "axios";
function UsersList() {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
axios
.get("https://jsonplaceholder.typicode.com/users")
.then((response) => {
setUsers(response.data);
setLoading(false);
})
.catch(() => {
setError("Unable to fetch data");
setLoading(false);
});
}, []);
if (loading) return <p>Loading...</p>;
if (error) return <p>{error}</p>;
return (
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
export default UsersList;
Axios automatically handles JSON parsing and error rejection.
Best Practice: Conditional Rendering
{loading && <Loader />}
{error && <ErrorMessage message={error} />}
{!loading && !error && <DataList data={data} />}
This approach keeps UI logic clean and readable.
Resetting Loading and Error States
Always reset states before making a new request.
setLoading(true);
setError(null);
Prevents showing old errors during new requests.
Handling Errors Gracefully
Instead of generic messages:
- Show user-friendly error messages
- Log detailed errors internally
- Avoid exposing sensitive server information
Advanced Pattern: Try-Catch with Async/Await
const fetchData = async () => {
try {
setLoading(true);
const response = await axios.get(url);
setData(response.data);
} catch (error) {
setError("Something went wrong");
} finally {
setLoading(false);
}
};
The finally block ensures loading state is updated correctly.
Common Mistakes in Handling Loading and Error States
- Forgetting to set loading to false
- Not resetting error state
- Showing error before loading completes
- Fetching data inside render
- Ignoring network failures
Best Practices Summary
- Always show loading indicators
- Handle API errors properly
- Use separate states for loading and error
- Use finally for clean state updates
- Keep UI responsive and informative
Interview Questions and Answers – Loading and Error States
1. Why are loading states important in React?
They inform users that data is being fetched.
2. How do you manage loading state?
Using useState and conditional rendering.
3. What happens if loading state is not handled?
Users may see blank or broken UI.
4. How do you handle API errors?
Using try-catch or catch blocks and error state.
5. What is the purpose of finally block?
To execute code regardless of success or failure.
6. Should loading and error be in the same state?
No, they should be managed separately.
7. How does Axios handle errors?
It rejects the promise for HTTP error responses.
8. Can loading states be reused?
Yes, using reusable components.
9. What should error messages contain?
User-friendly and clear information.
10. Is handling error state mandatory?
Yes, for production-ready applications.
Your Feedback
Help us improve by sharing your thoughts
At Online Learner, we're on a mission to ignite a passion for learning and empower individuals to reach their full potential. Founded by a team of dedicated educators and industry experts, our platform is designed to provide accessible and engaging educational resources for learners of all ages and backgrounds.
Terms Disclaimer About Us Contact Us
Copyright 2023-2025 © All rights reserved.
