Every React component goes through a sequence of stages during its existence — from creation to removal. These stages are collectively known as the Component Lifecycle.
Understanding the lifecycle helps you handle side effects, fetch data, clean up subscriptions, and optimize performance.
A React component passes through three main lifecycle phases:
In class components, React provides dedicated lifecycle methods that are called at specific moments:
constructor(), componentDidMount()componentDidUpdate()componentWillUnmount()
// Class component lifecycle demo (mount, update, unmount)
import React, { Component } from "react";
class LifecycleDemo extends Component {
constructor() {
super();
this.state = { count: 0 };
console.log("Constructor - Mounting");
}
componentDidMount() {
console.log("Component Mounted");
}
componentDidUpdate() {
console.log("Component Updated");
}
componentWillUnmount() {
console.log("Component Unmounted");
}
render() {
return (
<div>
<h3>Count: {this.state.count}</h3>
<button
onClick={() => this.setState({ count: this.state.count + 1 })}
>
Increment
</button>
</div>
);
}
}
componentDidMount() logs "Component Mounted".componentDidUpdate() logs "Component Updated".componentWillUnmount() runs and logs "Component Unmounted", which is the right place to perform cleanup.Functional components don’t have lifecycle methods. Instead, they use the useEffect() hook to perform lifecycle-like actions.
// Functional component lifecycle demo using useEffect
import { useState, useEffect } from "react";
function LifecycleDemo() {
const [count, setCount] = useState(0);
// Mounting + Updating
useEffect(() => {
console.log("Component Mounted or Updated");
});
// Mounting only (runs once)
useEffect(() => {
console.log("Component Mounted");
}, []);
// Unmounting (cleanup)
useEffect(() => {
return () => {
console.log("Component Unmounted");
};
}, []);
return (
<div>
<h3>Count: {count}</h3>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
);
}
export default LifecycleDemo;
useEffect(callback) → runs after every render (mount + update) like componentDidMount + componentDidUpdate.useEffect(callback, []) → runs only once after the first render like componentDidMount.useEffect(() => return cleanup, []) → the cleanup function runs when the component unmounts, similar to componentWillUnmount.This table shows how class lifecycle methods map to useEffect in functional components:
| Phase | Class Component | Functional Component |
|---|---|---|
| Mounting | componentDidMount() |
useEffect(callback, []) |
| Updating | componentDidUpdate() |
useEffect(callback) |
| Unmounting | componentWillUnmount() |
return cleanup inside useEffect() |
useEffect to avoid memory leaks when components unmount.componentWillUnmount or the useEffect cleanup.useEffect hooks for different concerns (e.g., one for fetching, one for subscriptions).useEffect(..., []).console.log inside effects).Goal: Understand how React manages component lifecycle phases — Mounting, Updating, and Unmounting — and how to handle side effects properly using lifecycle methods or hooks.