When I first moved from React class components to functional components, one of the biggest questions I had was: How do I replace componentDidMount?
In class components, componentDidMount is easy. It runs once after the component is mounted. But in functional components, we don’t have lifecycle methods in the same way.
That’s where the useEffect hook comes in. I’ve used this hook in dozens of real-world projects, from dashboards for US healthcare companies to financial reporting systems. And in this post, I’ll walk you through exactly how to replicate componentDidMount in functional components.
What is componentDidMount?
In React class components, componentDidMount is a lifecycle method that runs once, right after the component is inserted into the DOM.
Typical use cases include:
- Fetching data from an API
- Setting up subscriptions (like WebSocket or event listeners)
- Initializing third-party libraries (like charts or maps)
Here’s a simple class component to remind you how it works:
import React, { Component } from "react";
class Dashboard extends Component {
componentDidMount() {
console.log("Component has mounted!");
// Example: fetch data from API
fetch("https://api.example.com/data")
.then((response) => response.json())
.then((data) => console.log(data));
}
render() {
return <h1>Dashboard Loaded</h1>;
}
}
export default Dashboard;componentDidMount runs only once, after the component is rendered.
How to Simulate componentDidMount in Functional Components
In functional components, we don’t have lifecycle methods. Instead, we use the useEffect hook.
The trick is simple:
- Write your effect inside useEffect.
- Pass an empty dependency array [] as the second argument.
This ensures the effect runs only once, just like componentDidMount.
Method 1 – Use useEffect with an Empty Dependency Array
Here’s the most common way to replicate componentDidMount:
import React, { useEffect } from "react";
function Dashboard() {
useEffect(() => {
console.log("Component has mounted!");
// Example: fetch data when component loads
fetch("https://api.example.com/data")
.then((response) => response.json())
.then((data) => console.log(data));
}, []); // Empty array = run only once
return <h1>Dashboard Loaded</h1>;
}
export default Dashboard;You can see the output in the screenshot below.

The empty array ensures the effect runs only once, after the component mounts.
Method 2 – Use useEffect with Cleanup (Unmount Simulation)
Sometimes, you also want to clean up resources when the component unmounts. For example, removing an event listener.
import React, { useEffect } from "react";
function WindowTracker() {
useEffect(() => {
const handleResize = () => {
console.log("Window resized:", window.innerWidth);
};
window.addEventListener("resize", handleResize);
// Cleanup function runs on unmount
return () => {
window.removeEventListener("resize", handleResize);
console.log("Cleanup done!");
};
}, []);
return <h2>Resize the window and check the console</h2>;
}
export default WindowTracker;You can see the output in the screenshot below.

The cleanup function inside useEffect is like componentWillUnmount. It ensures we don’t leave memory leaks.
Method 3 – Fetch Data on Mount (Real-World Example)
Let’s say we’re building a US weather dashboard that fetches data from an API when the component mounts.
import React, { useEffect, useState } from "react";
function WeatherDashboard() {
const [weather, setWeather] = useState(null);
useEffect(() => {
async function fetchWeather() {
const response = await fetch(
"https://api.weatherapi.com/v1/current.json?key=demo&q=New York"
);
const data = await response.json();
setWeather(data);
}
fetchWeather();
}, []);
return (
<div>
<h1>Weather Dashboard</h1>
{weather ? (
<p>
{weather.location.name}: {weather.current.temp_f}°F
</p>
) : (
<p>Loading...</p>
)}
</div>
);
}
export default WeatherDashboard;This is a practical example where useEffect acts like componentDidMount to fetch data once.
Method 4 – Use a Custom Hook for Reusability
If you find yourself repeating the same logic, you can wrap it in a custom hook.
import React, { useEffect } from "react";
function useMountEffect(callback) {
useEffect(() => {
callback();
}, []);
}
function AnalyticsTracker() {
useMountEffect(() => {
console.log("Tracking page view...");
// Imagine sending analytics to Google Analytics
});
return <h3>Analytics Tracker Running</h3>;
}
export default AnalyticsTracker;You can see the output in the screenshot below.

Custom hooks help keep code clean and reusable across multiple components.
Common Mistakes to Avoid
Over the years, I’ve seen developers make these common mistakes when trying to use useEffect as componentDidMount:
- ❌ Forgetting the empty array
[]→ causes the effect to run on every render. - ❌ Adding unnecessary dependencies → makes the effect re-run more often than needed.
- ❌ Ignoring cleanup → can lead to memory leaks, especially with event listeners or subscriptions.
Always check your dependencies carefully and use cleanup functions when needed.
When Not to Use componentDidMount Logic
While useEffect is powerful, not every task belongs in a componentDidMount equivalent.
For example:
- Initializing state from props should be done directly in useState, not inside useEffect.
- Expensive calculations can often be memoized with useMemo instead of running them on mount.
Conclusion
Using componentDidMount in functional components is all about mastering the useEffect hook.
- Use an empty dependency array [] to run logic once on mount.
- Add a cleanup function if you need to remove listeners or free resources.
- Build reusable custom hooks for common patterns.
With these methods, you can confidently migrate from class components to functional components without losing lifecycle functionality.
I’ve been using these techniques in production apps for years, and they’ve never let me down. Once you get comfortable with useEffect, you’ll see just how flexible functional components can be.
You may read:
- Work with React Date Picker Component
- Build a Custom Input Component in React
- Force a React Component to Re-Render
- Build a React Multi-Select Component

I am Bijay Kumar, a Microsoft MVP in SharePoint. Apart from SharePoint, I started working on Python, Machine learning, and artificial intelligence for the last 5 years. During this time I got expertise in various Python libraries also like Tkinter, Pandas, NumPy, Turtle, Django, Matplotlib, Tensorflow, Scipy, Scikit-Learn, etc… for various clients in the United States, Canada, the United Kingdom, Australia, New Zealand, etc. Check out my profile.