📘 ReactJS

useEffect — Side Effects & API Calls

useEffect is used to synchronize a component with something outside normal rendering. Common examples are API requests, timers, subscriptions, browser events, and external systems.

S

Site Administrator

📅 Sep 28, 2026 🕒 3 min read 👁 26 views
☆ Save 𝕏 in f ✆
useEffect — Side Effects & API Calls

useEffect is used to synchronize a component with something outside normal rendering. Common examples are API requests, timers, subscriptions, browser events, and external systems.

1 What Is a Side Effect?

Rendering should calculate the UI. A side effect performs work involving something outside that calculation.

  • API calls
  • Timers
  • Subscriptions
  • Browser event listeners

2 Basic Syntax

useEffect(() => {
    console.log("Effect executed");
});

Without dependencies, the effect can run after every render.

3 Dependency Array

useEffect(() => {
    console.log("User:", userId);
}, [userId]);

The effect is synchronized again when userId changes.

4 Effect Flow

flowchart TD
A[Component Renders] --> B[React Commits UI]
B --> C[Effect Runs]
C --> D[External Work]
D --> E[State May Update]
E --> A

5 API Call Example

function Users() {
    const [users, setUsers] = useState([]);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState("");

    useEffect(() => {
        async function loadUsers() {
            try {
                const response = await fetch("/api/users");
                if (!response.ok) throw new Error("Unable to load users");
                setUsers(await response.json());
            } catch (error) {
                setError(error.message);
            } finally {
                setLoading(false);
            }
        }
        loadUsers();
    }, []);

    if (loading) return <p>Loading...</p>;
    if (error) return <p>{error}</p>;

    return <ul>{users.map(user => <li key={user.id}>{user.name}</li>)}</ul>;
}

6 Cleanup

useEffect(() => {
    const timerId = setInterval(() => console.log("Tick"), 1000);
    return () => clearInterval(timerId);
}, []);

Cleanup is important for timers, subscriptions, and event listeners.

7 API Race Conditions

If an old request finishes after a newer request, stale data can overwrite the latest result. AbortController can cancel the old request.

useEffect(() => {
    const controller = new AbortController();

    async function loadUser() {
        try {
            const response = await fetch(`/api/users/${userId}`, {
                signal: controller.signal
            });
            if (!response.ok) throw new Error("Request failed");
            setUser(await response.json());
        } catch (error) {
            if (error.name !== "AbortError") setError(error.message);
        }
    }

    loadUser();
    return () => controller.abort();
}, [userId]);

8 When Not to Use useEffect

Do not use an effect for a value that can be calculated directly from props or state.

const total = price * quantity;

9 Common Mistakes

  • Missing dependencies.
  • Using effects for simple calculations.
  • Forgetting cleanup.
  • Ignoring API race conditions.
  • Creating effects that continuously update their own dependencies.

10 Interview Questions

  1. What is useEffect?
  2. What is a side effect?
  3. What does the dependency array do?
  4. Why is cleanup needed?
  5. How do you call an API using useEffect?
  6. How can API race conditions be prevented?
  7. When should useEffect not be used?

11 Key Takeaways

  • useEffect synchronizes React with external systems.
  • Dependencies control synchronization.
  • Cleanup removes old external work.
  • API calls are a common use case.

Conclusion

The best way to understand useEffect is as a synchronization mechanism for external systems rather than simply as a lifecycle replacement.

Comments & Ratings (0)

Log in or create a student account to comment and rate this article.

Be the first to comment on this article.

Never miss a new post 📬

Get an email whenever a new article, project, cheatsheet or video drops.

✅

ℹ️