Fetching Data on Mount
Fetch JSON from an API inside useEffect, store the response in state, and trigger the fetch only once with an empty dependency array.
The Data Fetching Pattern
The standard React data fetching pattern: 1) define loading/error/data state, 2) fetch in useEffect with empty deps [], 3) update state in the callback, 4) render based on state.
Full Example
A complete example fetching users on mount with loading and error handling.
interface User { id: number; name: string; email: string; }
function UserList() {
const [users, setUsers] = useState<User[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
fetch('/api/users')
.then(res => {
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json();
})
.then(data => setUsers(data))
.catch(err => setError(err.message))
.finally(() => setLoading(false));
}, []);
if (loading) return <Spinner />;
if (error) return <ErrorMessage message={error} />;
return <ul>{users.map(u => <UserItem key={u.id} {...u} />)}</ul>;
}