πŸš€ Day 12 of Learning React: Understanding useEffect, Cleanup Functions, and API Calls

πŸš€ Day 12 of Learning React: Understanding useEffect, Cleanup Functions, and API Calls

# react# javascript# webdev# beginners
πŸš€ Day 12 of Learning React: Understanding useEffect, Cleanup Functions, and API CallsBismay.exe

πŸ“Œ Missed Day 11? Last time I finally understood why React has Context API, how it solves prop...

πŸ“Œ Missed Day 11? Last time I finally understood why React has Context API, how it solves prop drilling, and how multiple components can share the same state without passing props through every level. You can read it here and then come back. I'll wait. β˜•οΈ


After spending the last few days learning about state, Context API, and sharing data between components, I thought I had a pretty solid understanding of React.

Then today's lesson completely changed the way I think about rendering.

I used to assume React somehow "knew" when it should fetch data, start a timer, or clean up resources.

It doesn't.

React only has one main responsibility:

Render the UI.

Anything that needs to happen after rendering is considered a side effect.

And that's exactly why React gives us a hook called useEffect().

By the end of today's class, I realized useEffect isn't just another hook to memorize.

It's React's way of saying:

"If you want something to happen after rendering, tell me exactly when to do it."

Let's dive in. πŸš€


🧠 Quick Recap

Yesterday's big question was:

How can components share state without prop drilling?

Here's what I learned on Day 11:

  • 🌐 Context API helps avoid prop drilling.
  • πŸ“¦ createContext() creates a shared context.
  • πŸ—οΈ The Provider makes shared data available.
  • 🎣 useContext() lets components access that data directly.

Today, a completely different question came up.

How does React know when to run code after rendering? πŸ€”


πŸ€” The Mistake I Didn't Know I Was Making

Suppose I have a function that fetches products from an API.

const getData = async () => {
  let res = await axios.get("https://fakestoreapi.com/products");
  setApiData(res.data);
};
Enter fullscreen mode Exit fullscreen mode

My first instinct was simple.

Just call it inside the component.

function App() {
  getData();

  return <h1>Hello React</h1>;
}
Enter fullscreen mode Exit fullscreen mode

Looks harmless...

Right?

Not really.


πŸ”„ The Infinite Loop Problem

Here's what actually happens.

Component Renders
        ↓
getData() Runs
        ↓
setApiData()
        ↓
State Updates
        ↓
Component Renders Again
        ↓
getData() Runs Again
        ↓
...
Enter fullscreen mode Exit fullscreen mode

React isn't doing anything wrong here.

Every time the state changes...

React renders again.

Since getData() is inside the component, it runs again too.

Which updates the state.

Which causes another render.

Which calls getData() again.

And the cycle never ends.

That was the moment I realized:

React doesn't know that I only wanted to fetch the data once.

I have to tell it.


🎣 Enter useEffect()

That's where today's star finally entered the picture.

useEffect(() => {
  getData();
}, []);
Enter fullscreen mode Exit fullscreen mode

At first, this syntax looked strange.

Especially that empty array at the end.

What exactly is it doing?

Turns out...

That tiny array controls when the effect should run.


⚑ My First useEffect

Here's the exact code I used today.

useEffect(() => {
  getData();
}, []);
Enter fullscreen mode Exit fullscreen mode

This tells React:

"After the component renders for the first time, run getData()."

The important part is the empty dependency array.

[]
Enter fullscreen mode Exit fullscreen mode

It means:

Run this effect only once after the initial render.

Now the flow looks much cleaner.

Component Renders
        ↓
useEffect Runs
        ↓
API Request
        ↓
State Updates
        ↓
Component Re-renders
        ↓
Effect Doesn't Run Again βœ…
Enter fullscreen mode Exit fullscreen mode

That single change completely solved the problem.


🌐 My First API Request with Axios

Today's lesson also introduced me to Axios.

Before using it, I had to install it.

npm install axios
Enter fullscreen mode Exit fullscreen mode

Then importing it was straightforward.

import axios from "axios";
Enter fullscreen mode Exit fullscreen mode

Fetching data looked like this.

const getData = async () => {
  const res = await axios.get("https://fakestoreapi.com/products");

  setApiData(res.data);
};
Enter fullscreen mode Exit fullscreen mode

This was my first time using Axios instead of the built-in fetch() API.

One thing I immediately noticed was how simple the response felt.

With Axios, the actual data is already available inside:

res.data
Enter fullscreen mode Exit fullscreen mode

So after fetching the products, I simply updated my state.

setApiData(res.data);
Enter fullscreen mode Exit fullscreen mode

React re-rendered the component, and the products became available to display.

That felt much cleaner than I expected.


πŸ“Œ The Dependency Array Finally Made Sense

If I'm being honest...

The dependency array confused me more than useEffect() itself.

I kept wondering,

"Why is React asking me for an array?"

Eventually, I realized that the dependency array is simply React's way of knowing when an effect should run again.

There are three common patterns.

1️⃣ No Dependency Array

useEffect(() => {
  console.log("Running...");
});
Enter fullscreen mode Exit fullscreen mode

This runs after every render.

Render
   ↓
Effect

Render
   ↓
Effect

Render
   ↓
Effect
Enter fullscreen mode Exit fullscreen mode

2️⃣ Empty Dependency Array

useEffect(() => {
  console.log("Running...");
}, []);
Enter fullscreen mode Exit fullscreen mode

This runs only once.

First Render
      ↓
Effect Runs βœ…

Next Render
      ↓
Skipped
Enter fullscreen mode Exit fullscreen mode

3️⃣ Dependency Array with a Value

useEffect(() => {
  console.log("Count changed");
}, [count]);
Enter fullscreen mode Exit fullscreen mode

Now React watches count.

If count changes...

the effect runs again.

If it doesn't...

React skips it.

After seeing all three together, I stopped memorizing them and started thinking about what React was actually doing.

Dependency Array When it Runs
No array After every render
[] Only after the first render
[count] After the first render and whenever count changes

That tiny table made the dependency array much easier to remember.


🀯 The Experiment That Finally Made Cleanup Click

I thought today's biggest lesson would be fetching data from an API.

Surprisingly, the thing that impressed me the most had nothing to do with APIs.

It was understanding why React needs a cleanup function.

At first, I didn't understand why React lets us return a function inside useEffect().

useEffect(() => {
  console.log("About rendering...");

  return () => {
    console.log("Cleanup");
  };
}, []);
Enter fullscreen mode Exit fullscreen mode

Why would I return a function from another function?

It felt... unusual.

Then I tried a small experiment.


⏱️ The Interval That Wouldn't Stop

Inside my About component, I created an interval.

let interval = setInterval(() => {
  console.log("Hey, I'm in About");
}, 1000);
Enter fullscreen mode Exit fullscreen mode

Every second, the console printed:

Hey, I'm in About
Enter fullscreen mode Exit fullscreen mode

Exactly as expected.

Then I switched from the About component to the Contact component.

Since the About component disappeared...

I expected the logging to stop.

It didn't.

The console kept printing:

Hey, I'm in About
Hey, I'm in About
Hey, I'm in About
...
Enter fullscreen mode Exit fullscreen mode

That completely confused me.

The component wasn't even on the screen anymore.

So why was the interval still running?


πŸ’‘ React Removes Components... Not JavaScript

This was probably the biggest realization of today's lesson.

When React removes a component from the screen...

it only removes the component itself.

It doesn't automatically stop timers, intervals, or event listeners created by JavaScript.

Those things continue running unless I stop them myself.

That's exactly why the cleanup function exists.


🧹 The Cleanup Function

Here's the version that fixed everything.

useEffect(() => {
  let interval = setInterval(() => {
    console.log("Hey, I'm in About");
  }, 1000);

  return () => {
    clearInterval(interval);
  };
}, []);
Enter fullscreen mode Exit fullscreen mode

Here's how I visualize it now:

About Component Mounts
        ↓
Interval Starts
        ↓
User Switches Page
        ↓
Component Unmounts
        ↓
Cleanup Function Runs
        ↓
Interval Stops βœ…
Enter fullscreen mode Exit fullscreen mode

That finally made the purpose of cleanup click for me.

React isn't cleaning things automatically.

It's simply giving me one last chance to clean up anything my component created before it disappears.


πŸ”„ Mount, Re-render, and Unmount

Another thing I kept hearing today was:

  • Mount
  • Re-render
  • Unmount

At first, they sounded like complicated React terms.

But after today's examples, I started thinking about them much more simply.

Mount
↓
Component appears for the first time.

Re-render
↓
Component runs again because state or props changed.

Unmount
↓
Component is removed from the screen.
Enter fullscreen mode Exit fullscreen mode

That also explained why the cleanup function runs during unmounting.

React is basically saying:

"Your component is leaving. If you started anything, now is the time to stop it."


🧠 My Mental Model

This is how I picture useEffect() now.

Component Renders
        ↓
React Updates the UI
        ↓
useEffect Runs
        ↓
Side Effect Happens
(API Call, Timer, Event Listener...)
Enter fullscreen mode Exit fullscreen mode

And if the component is removed...

Component Unmounts
        ↓
Cleanup Function Runs
        ↓
Resources Are Released
Enter fullscreen mode Exit fullscreen mode

Thinking about it this way made today's lesson much easier to remember.


πŸ’‘ My Biggest Takeaways Today

  • 🎣 useEffect() lets React run code after rendering.
  • 🌐 API requests are a common use case for useEffect().
  • πŸ“¦ The dependency array controls when an effect runs.
  • ⚑ An empty dependency array ([]) runs the effect only once after the initial render.
  • 🧹 Cleanup functions stop things like intervals and event listeners before a component unmounts.
  • 🧠 React renders the UIβ€”but side effects are still my responsibility.

πŸ“š Learning Source

I'm currently learning React through React Cohort 3.0 by Devendra Dhote at Sheriyans Coding School.

This article is based on my own class notes, code experiments, and understanding. Writing these posts helps me reinforce what I've learned, and hopefully makes things a little easier for other beginners too.

If I've misunderstood something, I'd genuinely appreciate any corrections in the comments. 😊


πŸ™Œ Final Thoughts

Today's lesson completely changed how I think about React.

Before today's class, I thought useEffect() was mostly for fetching data from APIs.

By the end of the lesson, I realized API calls are just one example of a side effect.

The real purpose of useEffect() is much bigger.

It's React's way of letting us run code after rendering, while also giving us a chance to clean everything up when a component disappears.

The cleanup function was my favorite part of today's lesson.

Watching an interval continue running after a component disappeared was confusing at first, but once I understood why cleanup exists, everything finally clicked.

I'm starting to notice something interesting about React.

Every hook I've learned so far exists because it solves a very specific problem.

The more I understand those problems, the more React itself starts making sense.

See you on Day 13! πŸš€


πŸ’¬ What confused you the most when you first learned useEffect()? Was it the dependency array, the cleanup function, or simply knowing when to use it? I'd love to hear your experience in the comments. 😊

If you're following along with this series, you can also find me on GitHub, where I'll be sharing my projects and documenting my progress.

Bismay-exe (Bismay.exe) Β· GitHub

πŸ‘‹ Hi, I’m Bismay πŸ’» Developer passionate about building clean, minimal, and elegant apps πŸš€ Focused on coding 🌱 Always learning, creating & new ideas - Bismay-exe

favicon github.com

πŸ€– AI Disclosure: This article is based on my own React learning journey, class notes, code experiments, and understanding. I used ChatGPT to help improve the writing, structure, and readability of this post. I reviewed and verified the technical explanations before publishing, and I take responsibility for everything shared here.

Thanks for reading! πŸš€