🔄 Demystifying useEffect in React.js – The Sidekick You Never Knew You Needed 🦸‍♂️

Amandeep SinghAmandeep Singh
3 min read

Ah, useEffect. The one hook that either makes you feel like a React wizard 🧙‍♂️ or makes you want to throw your laptop out the window 💻🚀.

Let’s break it down, desi-style, meme-style, and code-style. Buckle up! 🎢

🧠 What is useEffect?

In simple terms: useEffect lets you run some code (a side-effect) after your component renders.

Imagine your React component is a movie 🎬. Rendering is the scene. useEffect is the background music or after-credits scene — something that happens alongside the main act.


🤷‍♂️ Why do we need it?

React is declarative. But what if you want to do things like:

  • Fetch data from an API 🌐

  • Set up a subscription 🧷

  • Add event listeners (like a scroll or resize) 🖱️

  • Update the DOM manually (rare, but hey… it happens) 💪

That’s where useEffect comes in.


⚙️ Basic Syntax

import { useEffect } from "react";
useEffect(() => {
  // your side-effect logic
});

By default, it runs after every render (yes, every 😩). But don’t worry, we’ll fix that.


🧪 Example 1: Console.log on Every Render

import { useEffect, useState } from "react";
function LoggerComponent() {
  const [count, setCount] = useState(0);
  useEffect(() => {
    console.log("Component rendered! 🔁");
  });
  return (
    <div>
      <p>You clicked {count} times.</p>
      <button onClick={() => setCount(count + 1)}>Click me!</button>
    </div>
  );
}

📌 Every time you click, useEffect runs.


🧯 Example 2: Run Only Once (on Mount)

Just like componentDidMount in class components.

useEffect(() => {
  console.log("Component mounted! 🚀");
}, []); // empty dependency array

✅ It runs only once when the component loads.


🔁 Example 3: Run When a Value Changes

useEffect(() => {
  console.log("Count changed:", count);
}, [count]); // runs only when 'count' changes

Think of this like saying:

“Hey React, only run this if count has changed, okay?"


🧹 Example 4: Cleanup on Unmount

Perfect for things like removing event listeners or cancelling timers.

useEffect(() => {
  const interval = setInterval(() => {
    console.log("Tick ⏱️");
  }, 1000);
  return () => {
    clearInterval(interval);
    console.log("Cleanup done 🧼");
  };
}, []);

🧼 The return function is the cleanup — React calls it when the component unmounts or before re-running the effect.


🧠 Mind = Blown: Dependency Gotchas 😵

Let’s say you’re fetching data based on id prop:

useEffect(() => {
  fetch(`/api/user/${id}`).then(...);
}, [id]);

✅ Good: only fetches when id changes.

🚨 Bad: if you forget [id], it'll run on every render.


🧙‍♂️ Golden Rules of useEffect

  1. Always add dependencies you use inside the effect.

  2. Use multiple useEffects for unrelated logic.

  3. Avoid putting async functions directly in useEffect (wrap them inside).

useEffect(() => { 

  async function fetchData() {     
    const res = await fetch(...);   
  }   
  fetchData(); 

}, []);

🧠 Real-World Example: Fetching Data

function UserProfile({ userId }) {

  const [user, setUser] = useState(null);

  useEffect(() => {

    let isMounted = true;

    async function fetchUser() {

      const res = await fetch(`/api/user/${userId}`);
      const data = await res.json();
      if (isMounted) setUser(data);

    }

    fetchUser();

    return () => {
      isMounted = false; // prevent state updates if unmounted
    };

  }, [userId]);

  if (!user) return <p>Loading...</p>;

  return <div>Hello, {user.name} 👋</div>;
}

TL;DR

  • useEffect(() => {}, []) = run once.

  • useEffect(() => {}, [value]) = run when value changes.

  • useEffect(() => { return () => {} }) = cleanup.

  • Always handle async stuff carefully 🧠.


🧶 Wrapping Up

useEffect is powerful. But with great power comes... yep, great responsibility 🕸️.

Use it wisely. Split your concerns. Don’t fear the dependency array — embrace it.

If you found this helpful (or at least mildly entertaining 😄), share it with your React buddies.

0
Subscribe to my newsletter

Read articles from Amandeep Singh directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Amandeep Singh
Amandeep Singh

At GetReplies we are building a SaaS product to craft personalized emails, messages to target 10% reply rate. Zolo fosters impactful contributions as an SDE-III, where frontend engineering expertise drives scalable web solutions. Proficiencies in ReactJS, Next.js, and Redux Toolkit enable the creation of user-centric, high-performance applications. Success is achieved through seamless collaboration and continuous improvement.