Design Converter
Education
Last updated on Mar 5, 2025
•5 mins read
Last updated on Mar 5, 2025
•5 mins read
Software Development Executive - I
Builds things that work. And if it doesn’t, he’ll fix it — with Neovim, of course.
Why do developers prefer React hooks over class-based components?
One big reason is useEffect. It simplifies side effects in functional components, making code cleaner and easier to manage.
But how does it compare to componentDidMount, the old way of handling side effects in class components?
This blog breaks down useEffect vs componentDidMount, explaining their differences, how they work, and when to use each. Understanding these will help developers write better React components with fewer headaches.
componentDidMount is a lifecycle method used in class-based components. It runs once when a component mounts, making it ideal for fetching data operations, subscriptions, or interactions with external APIs.
The component is created and inserted into the DOM.
componentDidMount is called after the first render.
Any function inside this method executes only once.
Here’s an example of using componentDidMount to fetch data from an API:
1import React, { Component } from "react"; 2 3class UserList extends Component { 4 state = { users: [] }; 5 6 componentDidMount() { 7 fetch("https://jsonplaceholder.typicode.com/users") 8 .then((response) => response.json()) 9 .then((data) => this.setState({ users: data })); 10 } 11 12 render() { 13 return ( 14 <ul> 15 {this.state.users.map((user) => ( 16 <li key={user.id}>{user.name}</li> 17 ))} 18 </ul> 19 ); 20 } 21} 22 23export default UserList;
• It runs after the component has been mounted.
• Used for API calls, event listeners, or subscriptions.
• Executes once unless the component is re-mounted.
The useEffect hook in functional components replaces componentDidMount, componentDidUpdate, and componentWillUnmount. It enables developers to carry out side operations like event listener setup, DOM updates, and data fetching.
The effect function is executed after the component renders.
It runs based on dependencies provided in the dependency array.
Cleanup function is executed before the component unmounts.
Here’s an example of using the useEffect hook to fetch data from an API:
1import React, { useState, useEffect } from "react"; 2 3const UserList = () => { 4 const [users, setUsers] = useState([]); 5 6 useEffect(() => { 7 fetch("<https://jsonplaceholder.typicode.com/users>") 8 .then((response) => response.json()) 9 .then((data) => setUsers(data)); 10 }, []); // Empty dependency array ensures it runs only once 11 12 return ( 13 <ul> 14 {users.map((user) => ( 15 <li key={user.id}>{user.name}</li> 16 ))} 17 </ul> 18 ); 19}; 20 21export default UserList;
The key difference between componentDidMount and the useEffect hook is how and when they are executed. Let’s compare them in various aspects.
Aspect | componentDidMount | useEffect with [] |
---|---|---|
When it runs | After the first render | After the first render |
Runs again on updates? | No | No (with an empty dependency array) |
Handles cleanup? | Requires componentWillUnmount | Supports a cleanup function |
The dependency array in the useEffect hook determines when it re-runs.
Dependency Array Usage | Behavior |
---|---|
useEffect(() => {...}, []) | Runs once (like componentDidMount) |
useEffect(() => {...}, [stateVariable]) | Runs when stateVariable changes |
useEffect(() => {...}) | Runs on every render |
useEffect supports a cleanup function, which helps avoid memory leaks.
1useEffect(() => { 2 const interval = setInterval(() => { 3 console.log("Interval running..."); 4 }, 1000); 5 6 return () => clearInterval(interval); // Cleanup function 7}, []);
In class-based components, this requires a separate componentWillUnmount method.
1componentWillUnmount() { 2 clearInterval(this.interval); 3}
By using an empty dependency array, the useEffect hook runs only once after the first render, mimicking componentDidMount.
1useEffect(() => { 2 console.log("Component mounted"); 3}, []); // Empty dependency array
Adding dependencies makes the effect run when those values change.
1useEffect(() => { 2 console.log("State changed!"); 3}, [count]); // Runs when `count` updates
Returning a function inside useEffect acts as a cleanup function, executed when the component unmounts.
1useEffect(() => { 2 const handleResize = () => console.log("Resized!"); 3 4 window.addEventListener("resize", handleResize); 5 6 return () => { 7 window.removeEventListener("resize", handleResize); // Cleanup function 8 }; 9}, []);
Use Case | Preferred Approach |
---|---|
Fetching API data | useEffect with an empty dependency array |
Subscribing to events | useEffect with cleanup function |
Updating state on mount | useEffect or componentDidMount |
Handling cleanup | useEffect with cleanup function |
Both componentDidMount and the useEffect hook allow developers to run side effects when a component mounts. The useEffect hook provides more flexibility, enabling multiple effects, dependency tracking, and an integrated cleanup function.
Using useEffect in functional components is the recommended approach for modern React applications over class components. It simplifies lifecycle method handling and ensures better performance by avoiding unnecessary re-renders.
Tired of manually designing screens, coding on weekends, and technical debt? Let DhiWise handle it for you!
You can build an e-commerce store, healthcare app, portfolio, blogging website, social media or admin panel right away. Use our library of 40+ pre-built free templates to create your first application using DhiWise.