Is useEffect an alternate for ComponentDidMount?

Parmeet SinghParmeet Singh
4 min read

Class-based components taught us a lot about React functionality and how it works. Two of the most used features are setState and ComponentDidMount. Developers who switched from class-based to function-based components started using useEffect for everything they used to do in ComponentDidMount. Many still believe that useEffect is a direct replacement. In this article, let's explore if this is true or not.

Initial Renders

Whenever a component is mounted, both ComponentDidMount and useEffect functions are called once (at least). See the below code and run it in your system -

Left is Function based and Right is Class Based.

Left is Functional Component and Right is Class Based Component. Below is the output you get -

So, both of them runs once whenever component mounts. Somewhere this is expected 😏.

Re-Renders?

Till here we have talked about “Mounting” Part. Now we are jumping on “Updating” Part. What would happen if I update something (state changes)? Would both functions trigger again? Let’s find out.

Output from Class Based Component -

Output from Functional Based Component -

Spot the difference?

When Class Based Component was ran, it first called “Constructor”, “Render Method” and then “ComponentDidMount”. But when “setState” is called or we can say when state changes, ComponentDidMount did not trigger itself. It’s clear that in whole component, it runs only ONCE.

On the other side, in Functional Based Component, it runs on initial render but also runs on whenever state changes (useState is called).

💡
useEffect doesn’t restrict itself here. useEffect accepts a callback and a DEPENDENCY ARRAY. This dependency array is game changer. But this is optional.
  • If dependency array is not mentioned, then useEffect runs on every render (whenever state changes). Like wise above example.

  • If dependency array exists but empty, then it runs only on initial render. In other words, for this scenario, it works exactly like ComponentDidMount.

  • If dependency array exists, with some values, then it runs on initial render and also whenever the state of mentioned variables changes.

Catch the Updates.

We can see the difference now. But one question arises: why did the React team design useEffect this way? There must have been something they noticed that made them realize the need for a function that can track both state changes and initial renders? Yes, there is! Let’s find out.

So, useEffect does a lot of work -

  1. Checks whether we have dependency array or not.

  2. If exists, then if it’s empty or filled.

  3. If empty, then run it only once when component mounts.

  4. If not empty, then run on mounting and every time the state of variable changes.

When we try to implement the above in Class Based Component, it looks like below -

import React from "react";

class UserClass extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            txt: "Hello",
            count: 0
        }
    }
    componentDidMount() {
        console.log("I am Component Did Mount.")
    }

    componentDidUpdate(prevProps, prevState) {
        if(this.state.txt !== prevState.txt) {
            //do something
        }
        if(this.state.count !== prevState.count) {
            //do something
        }
    }

    fakeButtonClick = () => {
        console.log("Button is Clicked from Class")
        this.setState({
            txt: "Hello World"
        })
    }

    render() {
        return (
            <div>
                <h1>Hello! I am a Class Based Component</h1>
                <button 
                onClick={this.fakeButtonClick}>
                    Click Me!
                </button>
                <p>{this.state.txt}</p>
            </div>
        )
    }
}

export default UserClass;

In the code above, ComponentDidMount runs first. Whenever we need to do something specific when a variable changes, we use ComponentDidUpdate. This function keeps track of the previous state and props, and we check if there’s any change with the current ones. Compared to useEffect, we just need to mention the variable name in the dependency array, and React tracks the changes automatically, reducing our work of making checks.

Class-based component code can become cluttered. Here, I added a couple of checks, but in production-ready code, there are numerous variables, arrays, and objects. Comparing them all can become a task in itself.

💡
This made Meta realise to combine all these tasks into a useEffect function 🦾

Now you know that useEffect is not exactly a replacement for ComponentDidMount. The tasks of ComponentDidMount and ComponentDidUpdate are combined into a single function, and it does even more (We will understand it in the next article). 😉

I hope you have learned something new today. If yes, give a like 😀

THANKS FOR READING UNTIL NEXT ONE 😜.

0
Subscribe to my newsletter

Read articles from Parmeet Singh directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Parmeet Singh
Parmeet Singh

Hi, I am Parmeet, a Software Engineer from India. 💡 Passionate about React, JS and algorithms that dance. When I’m not debugging, you can find me jamming out to playlists or swimming. Open doors to connect and let’s create something awesome together. 🌟