🔄 useEffect + fetch (with Loading & Error)
Fetching data in React using useEffect()
is a common pattern. Let's enhance our earlier example with a loading spinner and error message.
🛠️ Full Example with Loading & Error Handling
import React, { useEffect, useState } from 'react';
function UsersList() {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchUsers = async () => {
try {
const res = await fetch('https://jsonplaceholder.typicode.com/users');
if (!res.ok) throw new Error('Network response was not ok');
const data = await res.json();
setUsers(data);
setError(null);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
fetchUsers();
}, []);
if (loading) return <p>Loading users...</p>;
if (error) return <p style={{ color: 'red' }}>Error: {error}</p>;
return (
<div>
<h2>User List</h2>
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
}
export default UsersList;
🔍 Explanation
- loading: boolean to show spinner/message before data arrives
- error: captures any fetch or parsing issues
finally
ensures loading is turned off in both success/failure cases
This pattern is helpful in real-world apps where user feedback is critical.