useEffect

React is a powerful JavaScript library for building user interfaces, and it provides several special tools called Hooks to manage behavior in components. One of the most important and widely used hooks is useEffect.

What is useEffect?

useEffect is a React Hook that lets you run side effects in function components. Side effects include tasks like:

  • Fetching data from an API
  • Updating the DOM
  • Setting up event listeners
  • Working with timers like setInterval or setTimeout
  • Interacting with localStorage or cookies

In class components, we used lifecycle methods like componentDidMount, componentDidUpdate, and componentWillUnmount. In function components, useEffect combines all those lifecycle behaviors into a single hook.


Syntax of useEffect

import { useEffect } from 'react';

useEffect(() => {
// Code to run (side effect)
}, [dependencies]);

Parts of useEffect:

  • Callback Function: The function that runs after the component renders.
  • Dependency Array: Controls when the effect runs. It’s optional.

Example 1: Run Once (on Mount)

 useEffect(() => {
console.log("Component mounted");
}, []);

Explanation:
This effect runs only once, when the component mounts — similar to componentDidMount. It doesn’t run again unless the component is removed and added again.


Example 2: Run on State Change

 useEffect(() => {
console.log("The count changed!");
}, [count]);

Explanation:
This effect runs every time the count value changes.


Example 3: No Dependency (Run After Every Render)

 useEffect(() => {
console.log("Component re-rendered");
});

Explanation:
Without a dependency array, the effect runs after every render — including after props or state updates. Use this with caution to avoid performance issues.


Example 4: Cleanup (Unmount or Before Re-run)

 useEffect(() => {
const timer = setInterval(() => {
console.log("Running timer");
}, 1000);

// Cleanup function
return () => {
clearInterval(timer);
console.log("Cleanup");
};
}, []);

Explanation:
The returned function runs when the component unmounts or before the effect re-runs. This is useful for removing timers, event listeners, etc.


Common Uses of useEffect

TaskHow useEffect Helps
Fetch data from an APIRun fetch on mount and update state
Listen to window resizeAdd and clean up event listeners
Update document titleReact to state changes by updating the page title
Auto-save form dataSave input to localStorage whenever it changes

Best Practices

  • Always use a dependency array to avoid unnecessary re-renders.
  • Use cleanup to avoid memory leaks.
  • Avoid using async directly in the useEffect function — define an async function inside it if needed.

Avoiding Common Mistakes

Correct:

  useEffect(() => {
const fetchData = async () => {
const res = await fetch("https://api.example.com/data");
const data = await res.json();
console.log(data);
};
fetchData();
}, []);

Incorrect:

useEffect(async () => {
const res = await fetch("...");
}, []);

React does not support making the main useEffect function async, because it expects a cleanup function or nothing — not a Promise.


Summary

useEffect is one of the most essential hooks in React. It allows you to:

  • Perform side effects in function components
  • Control when and how effects run using the dependency array
  • Replace class-based lifecycle methods in modern React

By learning how to use useEffect properly, you can build interactive and dynamic components efficiently.