Sitemap
Vinay Kumar B R

Vinay Kumar B R

Software Engineer with 9+ years of experience in React, JavaScript (ES6+), TypeScript, Redux, Micro-Frontend Architecture.

Understanding useEffect Execution & Cleanup in React (With Examples)

3 min readJan 2, 2026

React’s useEffect hook often confuses developers- especially when multiple effects, dependency arrays, and cleanup functions are involved.

We’re often taught that useEffect behaves in three simple ways:
– Without a dependency array, it runs after every render.
– With an empty dependency array ([]), it runs only once after the component mounts.
– With dependencies, it runs whenever those dependencies change.

While this explanation is mostly (not 100%) correct, it’s an oversimplification. To truly understand useEffect, we also need to understand when cleanup functions run, why they are needed, and which effects should include cleanup.

Get Vinay Kumar B R’s stories in your inbox

Join Medium for free to get updates from this writer.

In this post, we’ll deeply understand how useEffect runs and cleans up using below example.

import { useState, useEffect } from "react";

export const Body = () => {

const [count, setCount] = useState(0);

useEffect(() => {
console.log("Component Mounted - No Dependency Array" );
return () => {
console.log("Cleanup - No Dependency Array" );
}
});

useEffect(() => {
console.log("Component Mounted - Empty Dependency Array" );
return () => {
console.log("Cleanup - Empty Dependency Array" );
}
}, []);


useEffect(() => {
console.log("Count value changed to: ", count);
return () => {
console.log("Cleanup - Count value before change: ", count);
}
}, [count]);

return (
<div>
<h1>Count value : {count}</h1>
<button onClick={() => setCount((prevCount) => prevCount + 1)}>Increment Count</button>
</div>
)
}

In above example we have 3 useEffect's .

  1. The useEffect without dependency array runs after every render (initial render and every state update). In this case cleanup runs on every time before the next render and when component unmount.
    We use this rarely in real world applications.
  2. The useEffect with empty dependency array runs only once after initial render. In this case cleanup runs only when component unmounts.
    This is the most common cleanup pattern because it executes only once when component mount and unmount, useful when we add and remove event listener. Start and stop timers.
  3. The useEffect with dependency array runs twice, once on initial render and whenever dependency update. In this case cleanup runs before effect re-runs and on component unmount.
    This we use rarely when an effect is tied to a specific value. I used this cleanup logic when I implemented debounce logic for my application to restart timer before timer expires.

Below is the log it prints when component mount for the first time. You can see that all effects run for the first time irrespective of second parameter.

Component Mounted - No Dependency Array
Component Mounted - Empty Dependency Array
Count value changed to: 0

Below is the log when it updated its state value, here you can see clearly that cleanup executed for useEffect which has no dependency array, then cleanup executed for useEffect which has dependency array. Then useEffect executed for both which has no dependency array and which has dependency array.

Cleanup - No Dependency Array
Cleanup - Count value before change: 0
Component Mounted - No Dependency Array
Count value changed to: 1

Below is the log when component is unmounted. Here you can see clean up method is called for all useEffect's .

Cleanup - Empty Dependency Array
Cleanup - No Dependency Array
Cleanup - Count value before change: 1

Conclusion

  1. useEffect always runs after the initial render, regardless of the dependency array.
  2. The dependency array only controls when the effect re-runs, not whether it runs the first time.
  3. Cleanup functions run either before the next effect execution (when dependencies change) or when the component unmounts.

Understanding this lifecycle clearly helps avoid confusion, unexpected logs, and side-effect bugs in React applications.

--

--

Vinay Kumar B R
Vinay Kumar B R

Written by Vinay Kumar B R

Software Engineer with 9+ years of experience in React, JavaScript (ES6+), TypeScript, Redux, Micro-Frontend Architecture.