Fetching Data with Effects

0/3 in this phase0/36 across the roadmap

📖 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:

  1. Initialize state for data, isLoading, and error.
  2. Use useEffect to trigger the fetch on mount (or when dependencies change).
  3. 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

codeTap to expand ⛶
1import React, { useState, useEffect } from 'react';
2
3function UserList() {
4 const [users, setUsers] = useState([]);
5 const [loading, setLoading] = useState(true);
6 const [error, setError] = useState(null);
7
8 useEffect(() => {
9 // 1. Define async function inside effect
10 const fetchUsers = async () => {
11 try {
12 setLoading(true);
13 const response = await fetch('https://jsonplaceholder.typicode.com/users');
14
15 if (!response.ok) {
16 throw new Error('Failed to fetch users');
17 }
18
19 const data = await response.json();
20 setUsers(data);
21 } catch (err) {
22 setError(err.message);
23 } finally {
24 setLoading(false);
25 }
26 };
27
28 fetchUsers();
29 }, []); // Empty deps = fetch on mount
30
31 // 2. Conditional rendering based on state
32 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>;
34
35 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

  1. Build a 'Product Search' component that fetches results from an API as the user types.
  2. Implement 'Pagination' for your user list. Fetch new data when the 'Next' page button is clicked.
  3. Use 'Axios' instead of 'fetch' and notice the differences (e.g., automatic JSON parsing, easier error handling).
  4. 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