Use componentDidMount in React Functional Components with useEffect

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.

componentDidMount in React Functional Components with useEffect

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.

Use componentDidMount in React Functional Components with useEffect

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.

Use componentDidMount in React Functional Components useEffect

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:

Leave a Comment

51 Python Programs

51 PYTHON PROGRAMS PDF FREE

Download a FREE PDF (112 Pages) Containing 51 Useful Python Programs.

pyython developer roadmap

Aspiring to be a Python developer?

Download a FREE PDF on how to become a Python developer.

Let’s be friends

Be the first to know about sales and special discounts.