Fetching Data with Effects
📖 Concept
Fetching data is one of the most common side effects in React. While libraries like TanStack Query are preferred for production, understanding how to do it manually with useEffect is essential.
The Basic Pattern:
- Initialize state for
data,isLoading, anderror. - Use
useEffectto trigger the fetch on mount (or when dependencies change). - Update state based on the API response.
Why State is needed:
Since fetching data is asynchronous, React needs to know when the data arrives so it can re-render the component. We use isLoading to show a spinner and error to show a message if things go wrong.
💻 Code Example
1import React, { useState, useEffect } from 'react';23function UserList() {4 const [users, setUsers] = useState([]);5 const [loading, setLoading] = useState(true);6 const [error, setError] = useState(null);78 useEffect(() => {9 // 1. Define async function inside effect10 const fetchUsers = async () => {11 try {12 setLoading(true);13 const response = await fetch('https://jsonplaceholder.typicode.com/users');1415 if (!response.ok) {16 throw new Error('Failed to fetch users');17 }1819 const data = await response.json();20 setUsers(data);21 } catch (err) {22 setError(err.message);23 } finally {24 setLoading(false);25 }26 };2728 fetchUsers();29 }, []); // Empty deps = fetch on mount3031 // 2. Conditional rendering based on state32 if (loading) return <div className="p-4 animate-pulse">Loading users...</div>;33 if (error) return <div className="p-4 text-red-500">Error: {error}</div>;3435 return (36 <ul className="divide-y border rounded">37 {users.map(user => (38 <li key={user.id} className="p-3 hover:bg-gray-50">39 <p className="font-bold">{user.name}</p>40 <p className="text-sm text-gray-500">{user.email}</p>41 </li>42 ))}43 </ul>44 );45}
🏋️ Practice Exercise
- Build a 'Product Search' component that fetches results from an API as the user types.
- Implement 'Pagination' for your user list. Fetch new data when the 'Next' page button is clicked.
- Use 'Axios' instead of 'fetch' and notice the differences (e.g., automatic JSON parsing, easier error handling).
- Create a component that fetches data from two different APIs and waits for both to finish before rendering.
⚠️ Common Mistakes
Not handling the loading state, leading to 'undefined' errors when trying to access data before it arrives.
Not handling errors, leaving the user with a broken UI if the API is down.
Forgetting to include the 'signal' or a 'cancel' flag to prevent setting state on unmounted components.
Triggering infinite fetch loops by not providing a dependency array.
💼 Interview Questions
🎤 Mock Interview
Practice a live interview for Fetching Data with Effects