ComponentDidMount in Functional Component
When I create a react functional component, I was confused about how to use class lifecycle methods. Because we cannot create lifecycle methods in functional components using the same syntax as a class component. I encountered strange side effects in my application and grumbled because I had never used class components before. I researched and found a way that we can use the useEffect() hook to manage ComponentDidMount() lifecycle similar to how we manage the state in functional component using the useState hook.
What is ComponentDidMount()?
componentDidMount() is one of the lifecycle methods and you can use this method only in class components. If you use ComponentDidMount(), it will be called only after your component has been rendered to the DOM. We can use this method to perform side effects such as fetching data from an API, setting up subscriptions, or modifying the DOM. You can use the useEffect() to do similar functionality in the functional components.
If you create a constructor, ComponentDidMount(), and render() methods, the constructor will be called first, then the render() method will be called, and the ComponentDidMount() method will be called last. For example:
class App extends React.Component{
constructor() {
super()
console.log("Constructor called")
}
componentDidMount() {
console.log("ComponentDidMount called")
}
render() {
console.log("Render method called")
return (
<div><h1>Component Did Mount</h1></div>
)
}
}
If you update any value in componentDidMount() using state, it calls the render() method again.
class App extends React.Component{
constructor() {
super()
console.log("Constructor called")
this.state={data:false}
}
componentDidMount() {
console.log("ComponentDidMount called")
this.setState({data:'true'})
}
render() {
console.log("Render method called")
return (
<div><h1>Component Did Mount</h1></div>
)
}
}
In this example, we’ve created the state “data” and set it to “false” in the constructor. And update the state “data” to “true’ in the componentDidMount() using the setState() method. See the output, after the ComponentDidMount() call, the render() method is called again. So now you have an idea of how componentDidMount() method works.
Implementing componentDidMount in a Functional Component
Most developers create a react application using only a functional component and perform all the tasks that can be done in the class component using the concept of the hook. useEffect is one of the most frequently used hooks by developers. You can use the useEffect hook to configure some logic after your component is initially rendered. Using this hook you can perform the functionality of componentDidMount and componentDidUpdate in the functional component.
If you are going to use the use effect hook in your activity component, you need to import {useEffect} it first. useEffect hook accepts a callback function that executes after the component render and empty dependency array ([]) as the second argument. You can pass multiple variables as a dependency, it may have props or states. So, the basic syntax for creating useEffect is:
import React, { useEffect } from 'react';
useEffect(() =>{
// This code will run after the component is mounted to the DOM
// Place your componentDidMount logic here
},[]); // The empty dependency array ensures that this effect runs only once
Normally, inside a class component, componentDidMount() is utilized in the following way:
componentDidMount(){
// Fetch user data from an API
fetch(URL)
.then((response) => response.json())
.then((data) => setUserData(data.list))
.catch((error) => console.error('Error fetching data:', error));
}
If you look at the code below, I’ve fetched the data from an API by using the useEffect() hook. We’ve passed the callback function as 1st argument, it makes an HTTP request using the fetch function to a specified URL. If there is an error during the fetch operation, the .catch method handles the error and logs it to the console. Then we passed an empty dependency array [] as the 2nd argument, which ensures that the useEffect hook runs only once after the initial render of the component. So, during the loading phase, it shows a “Loading…” message. Once the data is fetched, the list of user names is rendered.
const UserData = () => {
const [userData, setUserData] = useState(null);
useEffect(() => {
// Fetch user data from an API
fetch(URL)
.then((response) => response.json())
.then((data) => setUserData(data.list))
.catch((error) => console.error('Error fetching data:', error));
}, []); // The empty dependency array ensures this effect runs only once on initial render
return (
<div>
{userData ? (
<ul>
{userData.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
) : (
<p>Loading...</p>
)}
</div>
);
};
If you pass the 2nd argument as an empty dependency array [], it won’t run again because it assumes you don’t want to make any props or state variables dependent. We can also pass some dependencies like:
useEffect(() => {
// Fetch user data from an API
fetch(URL)
.then((response) => response.json())
.then((data) => setUserData(data.list))
.catch((error) => console.error('Error fetching data:', error));
}, [userData]); // The empty dependency array ensures this effect runs only once on initial render
In this above code, we’ve passed the state variable called ‘userDate’, so when the ‘userDate’ changes, the function will be called again.
Conclusion
We learned how to use the componentDidMount() method normally in the class component. And we talked through how we implement componentdidmount in the functional component. I hope that this post has helped you understand useEffect() hook.