React is classy!
You might have guessed from the title what this is going to be about. Yes! It’s about React Class-Based Components. Although the trend has now shifted towards Function-Based Components, it's still important for beginners to understand the concepts and see how it used to work.
More likely at this point, we have all seen this diagram -
A common visual representation of React Lifecycle Methods shows how React works behind the scenes. I have seen many people know about this but don't understand how it actually works in practice. We will dive more into the “Mounting” Part for this article.
Part 1 - Order of Execution
Let’s write a very basic Class Based Component and name it as “User.js” which looks like below -
import React from "react";
class User extends React.Component {
constructor(props) {
super(props);
console.log("From User Constructor!")
}
componentDidMount() {
console.log("From User Component Did Mount");
}
render() {
console.log("From User Render");
return (
<div>
<h1>Hello! I am a Class Based Component and I still exist.</h1>
</div>
)
}
}
export default User;
Start your React app, run it and below is the output you find -
Here, when this component is called, think of it as creating a new instance (like using the "new" operator behind the scenes). Therefore, the first part that runs is the Constructor. Then the Render method runs, and finally, ComponentDidMount. This is exactly how the diagram shows it.
Part 2 - Parent Child Execution
In the first part, our “User.js” was the only Class Based Component and it was called. Let's take it one step further. Create another Class Based Component and name it “About.js”. Call the “User.js” component from here. In other words, “About.js” will be the parent and “User.js” will be the child. It looks like this:
import React from "react";
import User from "./User";
class About extends React.Component {
constructor(props) {
super(props);
console.log("From About Constructor")
}
componentDidMount() {
console.log("From About Component Did Mount");
}
render() {
console.log("From About Render")
return (
<div>
<User/>
</div>
)
}
}
export default About;
And the output is -
WAIT! WAIT! WAIT! Did you see what happened? Can you spot the difference? In the first part, we saw the order of execution is Constructor, Render, and DidMount. But something unusual happened here! Shouldn’t About’s all methods be called first, and then User? Let's understand it.
Our app starts with “About.js”. A new instance is created and “constructor” is called.
Next turn is of “Render”. During the execution of render method, React found another component which is “User”. So, a new instance of user is now created.
Now the command goes to “User component”. It’s constructor will be called, render method will be called and it’s “ComponentDidMount” is called.
And finally, ComponentDidMount of “About” will be called.
WOW! React does cool things. Let’s take a moment and clap for it 👏. I will tell you why 😏
Part 3 (Final) - Multiple Child to Parent
Now, Add another “User” in “About.js” file. But here, we will pass some props to differentiate in the output. In “User.js” accept the props and log into the console. Something like below -
import React from "react";
import User from "./User";
class About extends React.Component {
constructor(props) {
super(props);
console.log("From About Constructor")
}
componentDidMount() {
console.log("From About Component Did Mount");
}
render() {
console.log("From About Render")
return (
<div>
<User name="First User"/>
<User name="Second User"/>
</div>
)
}
}
export default About;
and the output looks like -
So this works exactly like our part-2, but just another component is added.
I would like to draw your attention on a pattern. Try to compare outputs from part 3 and part 2 and guess what’s actually React is doing.
React does a lot of optimisations when we write code. The one optimisation is how your app “reacts” to changes and how those changes will be rendered on UI.
Behind the scenes, React knows the DOM manipulation is an expensive task. So it takes care of that very optimally. HOW?
Calling a constructor is automatic when class is called and initial rendering doesn’t involve any DOM effects. So those are happening step wise (we can see in the output - First “About”, then “First User” and then “Second User”).
The catch happens when “ComponentDidMount” is called. We can see that every “ComponentDidMount” log for each component happens at the end because React knows this could involve an expensive operation (like an API call or state changes). So, the magic is that React bundles all the “ComponentDidMount” operations and runs them in a single batch 🤯. React aims to avoid a bad user experience, so it renders the content first and then performs the manipulations. By the way, this process is really FAST!
Phew! Now you might get it why I asked to clap 😌
CONCLUSION
My aim to write this article is many people who are new to React, directly jumps on to the Functional Components. The actual React and its concepts were when Classes were used. Although, there could be some legacy projects where classes are still used. This shows how React works behind the scenes and how React has evolved over the years.
I HOPE YOU WOULD LIKE THIS ARTICLE.
THANKS FOR READING 😊
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. 🌟