Welcome back to the React Mastery Series!
In the previous article, we explored Forms in React and learned how controlled components help React manage user input.
Today, we will dive into one of the most important and widely used React Hooks:
useEffect Hook
useEffect is a fundamental Hook used in almost every real-world React application.
It helps us perform side effects such as:
- Fetching data from APIs
- Updating browser titles
- Subscribing to events
- Setting timers
- Connecting to WebSockets
- Cleaning up resources
Understanding useEffect is essential for building production-ready React applications.
What Are Side Effects?
Before understanding useEffect, we need to understand what a side effect is.
A side effect is any operation that happens outside the normal component rendering process.
Examples:
API Calls
Component Render
|
↓
Call Backend API
|
↓
Receive Data
|
↓
Update State
Enter fullscreen mode Exit fullscreen mode
Browser Interaction
Examples:
- Changing document title
- Accessing local storage
- Manipulating browser APIs
Subscriptions
Examples:
- WebSocket connections
- Event listeners
- Timers
Why Do We Need useEffect?
React components should ideally be pure functions.
Example:
function UserProfile() {
return <h1>User Profile</h1>;
}
Enter fullscreen mode Exit fullscreen mode
The component receives data and returns UI.
However, real applications need external interactions.
Example:
Render Component
|
↓
Fetch User Data
|
↓
Update UI
Enter fullscreen mode Exit fullscreen mode
React provides useEffect to handle these operations safely.
Basic Syntax of useEffect
useEffect(() => {
// Side effect logic
}, []);
Enter fullscreen mode Exit fullscreen mode
The Hook accepts two parameters:
useEffect(
function,
dependency array
)
Enter fullscreen mode Exit fullscreen mode
First Parameter: Effect Function
This contains the code that should execute.
Example:
useEffect(() => {
console.log("Component rendered");
});
Enter fullscreen mode Exit fullscreen mode
Second Parameter: Dependency Array
The dependency array controls when the effect runs.
Example:
useEffect(() => {
console.log("Runs once");
}, []);
Enter fullscreen mode Exit fullscreen mode
The empty array means:
Run this effect only after the initial render.
Understanding useEffect Execution
Consider:
function App() {
useEffect(() => {
console.log("Effect executed");
}, []);
return <h1>Hello React</h1>;
}
Enter fullscreen mode Exit fullscreen mode
Execution flow:
Component Created
|
↓
Initial Render
|
↓
DOM Updated
|
↓
useEffect Executes
Enter fullscreen mode Exit fullscreen mode
Important:
useEffect runs after the component renders.
useEffect Without Dependency Array
Example:
useEffect(()=>{
console.log("Runs every render");
});
Enter fullscreen mode Exit fullscreen mode
Execution:
Initial Render
↓
Effect Runs
State Update
↓
Render
↓
Effect Runs Again
Enter fullscreen mode Exit fullscreen mode
This happens after every render.
Use carefully.
useEffect With Empty Dependency Array
Example:
useEffect(()=>{
console.log("Runs once");
},[]);
Enter fullscreen mode Exit fullscreen mode
Execution:
Component Mount
|
↓
Effect Executes Once
Enter fullscreen mode Exit fullscreen mode
Common use cases:
- Initial API calls
- Loading configuration
- Setting up subscriptions
useEffect With Dependencies
Example:
useEffect(()=>{
console.log("User changed");
},[userId]);
Enter fullscreen mode Exit fullscreen mode
Now the effect runs when:
userId changes
Enter fullscreen mode Exit fullscreen mode
Example:
setUserId(10);
Enter fullscreen mode Exit fullscreen mode
Flow:
State Update
|
↓
Component Re-render
|
↓
Dependency Changed
|
↓
useEffect Executes
Enter fullscreen mode Exit fullscreen mode
Real-World Example: Fetching API Data
A common React pattern:
import { useEffect, useState } from "react";
function Users() {
const [users, setUsers] = useState([]);
useEffect(() => {
fetch("https://api.example.com/users")
.then((response) => response.json())
.then((data) => {
setUsers(data);
});
}, []);
return (
<div>
{users.map((user) => (
<h3 key={user.id}>{user.name}</h3>
))}
</div>
);
}
Enter fullscreen mode Exit fullscreen mode
Flow:
Component Loads
|
↓
useEffect Runs
|
↓
API Request
|
↓
Receive Response
|
↓
Update State
|
↓
Render User List
Enter fullscreen mode Exit fullscreen mode
Cleanup Function in useEffect
Some effects need cleanup.
Examples:
- Removing event listeners
- Clearing timers
- Closing WebSocket connections
Example:
useEffect(() => {
const timer =
setInterval(() => {
console.log("Running");
}, 1000);
return () => {
clearInterval(timer);
};
}, []);
Enter fullscreen mode Exit fullscreen mode
The function returned from useEffect is called Cleanup Function
Component Lifecycle Using useEffect
In class components:
componentDidMount()
componentDidUpdate()
componentWillUnmount()
Enter fullscreen mode Exit fullscreen mode
In functional components:
useEffect handles all lifecycle behavior.
Mounting
Equivalent to:
componentDidMount()
Enter fullscreen mode Exit fullscreen mode
Example:
useEffect(()=>{
loadData();
},[]);
Enter fullscreen mode Exit fullscreen mode
Runs once when component appears.
Updating
Equivalent to:
componentDidUpdate()
Enter fullscreen mode Exit fullscreen mode
Example:
useEffect(()=>{
searchProducts();
},[searchText]);
Enter fullscreen mode Exit fullscreen mode
Runs whenever searchText changes.
Unmounting
Equivalent to:
componentWillUnmount()
Enter fullscreen mode Exit fullscreen mode
Example:
useEffect(() => {
return () => {
disconnect();
};
}, []);
Enter fullscreen mode Exit fullscreen mode
Runs when component is removed.
Real-World Example: WebSocket Connection
Imagine a live banking notification system.
Component loads:
Open Dashboard
|
↓
Create WebSocket Connection
|
↓
Receive Transaction Alerts
Enter fullscreen mode Exit fullscreen mode
When user leaves:
Navigate Away
|
↓
Close WebSocket
Enter fullscreen mode Exit fullscreen mode
Implementation:
useEffect(() => {
const socket =
new WebSocket(
"wss://bank.com/alerts"
);
return () => {
socket.close();
};
}, []);
Enter fullscreen mode Exit fullscreen mode
Dependency Array Mistakes
Mistake 1: Missing Dependencies
Example:
useEffect(()=>{
fetchUser(userId);
},[]);
Enter fullscreen mode Exit fullscreen mode
Problem:
userId is used but not included.
Correct:
useEffect(()=>{
fetchUser(userId);
},[userId]);
Enter fullscreen mode Exit fullscreen mode
Mistake 2: Infinite Loops
Example:
useEffect(()=>{
setCount(count+1);
},[count]);
Enter fullscreen mode Exit fullscreen mode
Flow:
count changes
|
↓
Effect runs
|
↓
setCount()
|
↓
count changes again
|
↓
Infinite Loop
Enter fullscreen mode Exit fullscreen mode
useEffect vs Event Handlers
A common confusion:
Should something happen inside:
- useEffect?
- Button click handler?
Example:
User clicks save button:
<button onClick={saveData}> Save </button>
Enter fullscreen mode Exit fullscreen mode
This belongs in an event handler.
Automatic behavior:
Component Loaded
|
↓
Fetch Data
Enter fullscreen mode Exit fullscreen mode
This belongs in:
useEffect()
Enter fullscreen mode Exit fullscreen mode
useEffect Best Practices
Keep Effects Focused
Avoid:
useEffect(()=>{
fetchData();
updateTitle();
connectSocket();
},[]);
Enter fullscreen mode Exit fullscreen mode
Better:
useEffect(()=>{
fetchData();
},[]);
useEffect(()=>{
connectSocket();
},[]);
Enter fullscreen mode Exit fullscreen mode
Avoid Unnecessary Effects
Do not use effects for simple calculations.
Avoid:
useEffect(()=>{
setFullName( firstName + lastName);
},[firstName,lastName]);
Enter fullscreen mode Exit fullscreen mode
Instead:
const fullName = firstName + lastName;
Enter fullscreen mode Exit fullscreen mode
Always Cleanup Resources
Cleanup:
- Timers
- Subscriptions
- Event listeners
- Connections
Enterprise Example: Banking Dashboard
Consider a retail banking application.
When the dashboard opens:
User Opens Dashboard
|
↓
useEffect Executes
|
↓
Fetch Account Summary API
|
↓
Fetch Transactions API
|
↓
Update State
|
↓
Render Dashboard
Enter fullscreen mode Exit fullscreen mode
When leaving:
User Leaves Page
|
↓
Cleanup Runs
|
↓
Close Connections
Enter fullscreen mode Exit fullscreen mode
This pattern is used in production React applications.
Key Takeaways
Today, we learned:
✅ useEffect handles side effects in React.
✅ Effects run after rendering.
✅ Dependency arrays control execution timing.
✅ Empty dependency arrays run effects once.
✅ Cleanup functions prevent memory leaks.
✅ API calls, subscriptions, and timers commonly use useEffect.
Coming Next 🚀
In Day 14, we will explore:
React Hooks Deep Dive – useRef and useMemo
We will learn:
- What useRef is
- Accessing DOM elements
- Persisting values without re-rendering
- useMemo for performance optimization
- Expensive calculations
- Real-world optimization examples
These Hooks are essential for writing high-performance React applications.
Happy Coding! 🚀
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.