Fetching Data in React
Fetching Data in React
From Static to Dynamic with API Calls
By AI Learning Assistant · React · useEffect · Fetch API · Custom Hooks
🤖 YOUR KIND AI LEARNING ASSISTANT
Hello learner! Today we're learning something really exciting: how to bring LIVE data into your React apps. Until now, we used hard‑coded data. But real apps show posts from servers, products from databases, messages from friends. I'll explain every concept in simple words, step by step. No rush take your time. You've got this! 💪
Why Fetch Data from an API?
FROM STATIC TO DYNAMIC APPLICATIONS
Imagine you're building a blog. You could write every article inside your code — but that would be terrible. Every time you publish a new article, you'd have to rewrite and redeploy the whole app. Instead, you store articles in a database and write one component that FETCHES them on demand. That's what APIs do — they give your app a way to ask for data.
In React, fetching data happens inside useEffect because it's a "side effect" — something that happens after the component renders. The browser needs to go out to the internet, ask a server for data, wait for the response, and then update the screen.
While waiting, your app should show a loading message. If something goes wrong (no internet, server down), show an error. When data arrives, display it. These three states — loading, error, success — are the heart of data fetching.
🎯 A SIMPLE ANALOGY
You order a pizza 🍕 (fetch data). The delivery person drives to the restaurant (API call). You wait at the door (loading state). If the pizza arrives, you eat (success). If the driver gets lost, you get a call saying sorry (error). Without these steps, you'd just stand there confused. That's why we show loading indicators and error messages!
How to Fetch Data Step by Step
fetch() · useEffect() · useState() for loading, error, data
We'll use a free fake API called JSONPlaceholder. It gives us fake blog posts for testing. No real data, just a playground.
Step 1 — Create state for the data, loading flag, and error
Step 2 — Inside useEffect (empty dependency array so it runs once), write an async function
Step 3 — Use fetch(url), await response, check if response.ok, then await response.json()
Step 4 — Update state (setData, setLoading(false)) and catch errors
Step 5 — Render different UI based on loading, error, or success
📜 CODE — Full Learning Feed Component (with detailed comments)
// ============================================ // Webbo3 Learning Feed — Fetches live blog posts // ============================================ import { useState, useEffect } from "react"; function App() { // State for the posts we fetch (initially empty array) const [posts, setPosts] = useState([]); // Loading state — true while fetching, false when done const [loading, setLoading] = useState(true); // Error state — null means no error, otherwise an error message const [error, setError] = useState(null); // This effect runs once when the component first appears useEffect(() => { // We need to define an async function inside (useEffect itself cannot be async) const fetchPosts = async () => { try { // Go to the internet and ask for data const response = await fetch("https://jsonplaceholder.typicode.com/posts?_limit=8"); // If response is not OK (e.g., 404 Not Found, 500 Server Error), throw an error if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } // Convert the response from JSON format to a JavaScript array const data = await response.json(); // Save the posts to state setPosts(data); // Turn off loading — we have the data now setLoading(false); } catch (err) { // Something went wrong — save the error message setError(err.message); setLoading(false); } }; // Call the fetch function fetchPosts(); }, []); // Empty array = run only once when component mounts // While loading, show this if (loading) { returnLoading Webbo3 articles...
; } // If there's an error, show error message if (error) { returnError: {error}; } // Success! Show the list of posts return ( <div style={{ padding: "40px" }}> <h1>Webbo3 Learning Feedh1> {posts.map(post => ( <div key={post.id} style={{ border: "1px solid #ccc", padding: "15px", marginBottom: "10px", borderRadius: "8px" }}> <h3>{post.title}h3> <p>{post.body}p> div> ))} div> ); } export default App;
🎯 Live Simulation — See Exactly How It Works
Webbo3 Learning Feed
Understanding React Hooks
Hooks let you use state and lifecycle in function components. Learn useState and useEffect today.
Building Your First Custom Hook
Extract reusable logic into custom hooks to keep components clean and testable.
Fetching Data with useEffect
Learn the three‑state pattern: loading, error, success.
React Query vs useEffect
Compare the built‑in approach with React Query for caching and background updates.
Styling React Apps
Explore CSS Modules, Styled Components, and Tailwind CSS.
✨ After 1.5 seconds (simulating network delay), the articles appear. This is exactly what your React app will do!
Making It Reusable — The useFetch Hook
DON'T REPEAT YOURSELF
If you fetch data in many components, you'll repeat the same boilerplate. React lets you create custom hooks — functions that start with "use" and can call other hooks. Here's a reusable useFetch hook.
// ============================================ // useFetch.js — A custom hook for any API call // ============================================ import { useState, useEffect } from "react"; function useFetch(url) { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchData = async () => { try { const res = await fetch(url); if (!res.ok) throw new Error(`Status ${res.status}`); const json = await res.json(); setData(json); } catch (err) { setError(err.message); } finally { setLoading(false); } }; fetchData(); }, [url]); // Re-run if the URL changes return { data, loading, error }; } export default useFetch; // ============================================ // Usage in any component becomes super clean! // ============================================ import useFetch from "./useFetch"; function App() { const { data: posts, loading, error } = useFetch("https://jsonplaceholder.typicode.com/posts?_limit=8"); if (loading) returnLoading...; if (error) returnError: {error}; return ( <div> {posts.map(post => <PostCard key={post.id} title={post.title} body={post.body} />)} div> ); }
Comparison — useEffect vs React Query
| Feature | useEffect + fetch | React Query |
|---|---|---|
| Code length | Long (boilerplate) | Short |
| Caching | Manual | Automatic |
| Background refetching | Not built in | Yes |
| Race condition safe | No (extra work) | Yes |
| Devtools | None | Excellent |
| Best for | Simple apps, learning | Production apps, complex data |
🤗 YOUR KIND AI ASSISTANT — ALWAYS HERE
💬 "My data shows up, then disappears!" → You might be resetting loading inside the effect incorrectly. Check your dependencies array.
💬 "I get a CORS error" → That means the API doesn't allow requests from your domain. For learning, use JSONPlaceholder (it allows all). For real APIs, you may need a backend proxy.
💬 "How do I POST data (send data to server)?" → Great question! You'll use fetch with method: "POST" and body: JSON.stringify(data). We'll cover that next week!
You made it through Day 24! Data fetching is a superpower — now you can connect your React apps to the entire internet. Celebrate every small win. You're doing amazing! 🎉
AI-Assisted JavaScript Learning · Fetching Data in React · From Static to Dynamic
Complete this lesson
Mark as complete to track your progress