React Mastery / React Hooks

Fetching data with useEffect

1️⃣ Why do we use useEffect for data fetching?

  • Fetching data from an API is a side effect.

  • Side effects:

    • Communicate with external servers

    • Are asynchronous

    • Should not block UI rendering

  • Fetching data directly inside a component body:

    • Runs on every render

    • Can cause infinite loops

  • useEffect allows us to control when the API call runs, usually:

    • Once when the component mounts


2️⃣ What do we need?

  • useState → store API data

  • useEffect → run API call after render

  • Axios → make HTTP requests

  • Loader state → show loading status to users

import React, { useState, useEffect } from "react";
import axios from "axios";

3️⃣ State setup

const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(true);
  • posts → stores fetched data

  • loading → controls loader visibility


4️⃣ Fetch data using useEffect

  • useEffect runs after the first render

  • Empty dependency array ([]) ensures:

    • API call runs only once

    • Same behavior as componentDidMount

useEffect(() => {
  axios
    .get("<https://jsonplaceholder.typicode.com/posts>")
    .then(response => {
      setPosts(response.data);
      setLoading(false);
    })
    .catch(error => {
      console.error("Error fetching posts:", error);
      setLoading(false);
    });
}, []);

5️⃣ Rendering data with loader

  • While loading → show loader

  • After data loads → show posts list

{loading ? (
  <p>Loading posts...</p>
) : (
  <ul>
    {posts.map(post => (
      <li key={post.id}>{post.title}</li>
    ))}
  </ul>
)}

6️⃣ Dependency array explained

Dependency Array

Behavior

[]

Runs once on mount

[value]

Runs when value changes

❌ Omitted

Runs after every render (avoid for fetch)


7️⃣ Common beginner mistakes ❌

  • Forgetting dependency array → infinite API calls

  • Fetching inside render or JSX

  • Adding posts to dependency array unnecessarily

  • Not stopping loader on error


8️⃣ Simple execution flow

  1. Component renders → loader shown

  2. useEffect runs after render

  3. API request is sent

  4. Data received → state updated

  5. Component re-renders → data displayed


🔚 In short

useEffect is the correct place for data fetching, and a loader improves user experience during async operations.


FULL WORKING EXAMPLE