React Lifecycle with Class and Hooks: 2024
The React lifecycle consists of a series of methods that are invoked at different stages of a component’s existence. These methods are broadly categorized into three phases: Mounting, Updating, and Unmounting. Here’s a detailed look at each phase, along with examples:
Class Component Life Cycle:
1. Mounting Phase
This phase occurs when a component is being inserted into the DOM.
a. constructor()
- Purpose: Initialize state and bind methods.
- Example:
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { counter: 0 };
}
}
b. static getDerivedStateFromProps(props, state)
- Purpose: Update state based on props.
- Example:
static getDerivedStateFromProps(props, state) {
if (props.reset) {
return { counter: 0 };
}
return null;
}
c. render()
- Purpose: Describe what the UI should look like.
- Example:
render() {
return <div>Counter: {this.state.counter}</div>;
}
d. componentDidMount()
- Purpose: Perform side effects, like fetching data.
- Example:
componentDidMount() {
console.log('Component has been mounted');
}
2. Updating Phase
This phase occurs when a component is being re-rendered due to changes in props or state.
a. static getDerivedStateFromProps(props, state)
- Purpose: Same as in the mounting phase.
- Example:
static getDerivedStateFromProps(props, state) {
if (props.reset) {
return { counter: 0 };
}
return null;
}
b. shouldComponentUpdate(nextProps, nextState)
- Purpose: Optimize re-rendering by returning
true
orfalse
. - Example:
shouldComponentUpdate(nextProps, nextState) {
return nextState.counter !== this.state.counter;
}
c. render()
- Purpose: Same as in the mounting phase.
- Example:
render() {
return <div>Counter: {this.state.counter}</div>;
}
d. getSnapshotBeforeUpdate(prevProps, prevState)
- Purpose: Capture information from the DOM before it changes.
- Example:
getSnapshotBeforeUpdate(prevProps, prevState) {
if (prevState.counter < this.state.counter) {
return { prevCounter: prevState.counter };
}
return null;
}
e. componentDidUpdate(prevProps, prevState, snapshot)
- Purpose: Perform side effects after the component has been updated.
- Example:
componentDidUpdate(prevProps, prevState, snapshot) {
if (snapshot) {
console.log('Previous counter:', snapshot.prevCounter);
}
}
3. Unmounting Phase
This phase occurs when a component is being removed from the DOM.
a. componentWillUnmount()
- Purpose: Perform cleanup tasks.
- Example:
componentWillUnmount() {
console.log('Component is being unmounted');
}
Full Example
Here’s a complete example that demonstrates the React lifecycle methods in a class component:
import React from 'react';
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { counter: 0 };
console.log('Constructor');
}
static getDerivedStateFromProps(props, state) {
console.log('getDerivedStateFromProps');
if (props.reset) {
return { counter: 0 };
}
return null;
}
componentDidMount() {
console.log('componentDidMount');
}
shouldComponentUpdate(nextProps, nextState) {
console.log('shouldComponentUpdate');
return nextState.counter !== this.state.counter;
}
getSnapshotBeforeUpdate(prevProps, prevState) {
console.log('getSnapshotBeforeUpdate');
if (prevState.counter < this.state.counter) {
return { prevCounter: prevState.counter };
}
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
console.log('componentDidUpdate');
if (snapshot) {
console.log('Previous counter:', snapshot.prevCounter);
}
}
componentWillUnmount() {
console.log('componentWillUnmount');
}
increment = () => {
this.setState({ counter: this.state.counter + 1 });
};
render() {
console.log('Render');
return (
<div>
<p>Counter: {this.state.counter}</p>
<button onClick={this.increment}>Increment</button>
</div>
);
}
}
export default MyComponent;
In this example, the lifecycle methods log messages to the console, providing a clear view of when each method is called during the component’s lifecycle. The increment
method updates the state, demonstrating the update lifecycle methods.
Hooks Component Life Cycle:
React hooks provide a way to use state and lifecycle features in functional components. Instead of using lifecycle methods like in class components, hooks offer a more modular and reusable approach. Here’s how you can achieve the same lifecycle functionalities in functional components using hooks:
1. Mounting Phase
a. useState
- Purpose: Initialize state.
- Example:
import React, { useState } from 'react';
function MyComponent() {
const [counter, setCounter] = useState(0);
return <div>Counter: {counter}</div>;
}
b. useEffect
(componentDidMount equivalent)
- Purpose: Perform side effects, like fetching data, after the component mounts.
- Example:
import React, { useState, useEffect } from 'react';
function MyComponent() {
const [counter, setCounter] = useState(0);
useEffect(() => {
console.log('Component has been mounted');
}, []); // Empty dependency array ensures this runs only once after mount
return <div>Counter: {counter}</div>;
}
2. Updating Phase
a. useEffect
(componentDidUpdate equivalent)
- Purpose: Perform side effects after state or props change.
- Example:
import React, { useState, useEffect } from 'react';
function MyComponent() {
const [counter, setCounter] = useState(0);
useEffect(() => {
console.log('Counter has been updated:', counter);
}, [counter]); // Dependency array ensures this runs whenever counter changes
return (
<div>
<p>Counter: {counter}</p>
<button onClick={() => setCounter(counter + 1)}>Increment</button>
</div>
);
}
3. Unmounting Phase
a. useEffect
(componentWillUnmount equivalent)
- Purpose: Perform cleanup tasks.
- Example:
import React, { useState, useEffect } from 'react';
function MyComponent() {
const [counter, setCounter] = useState(0);
useEffect(() => {
return () => {
console.log('Component is being unmounted');
};
}, []); // Empty dependency array ensures this cleanup runs only once before unmount
return <div>Counter: {counter}</div>;
}
Full Example
Here’s a complete example demonstrating all the phases using hooks:
import React, { useState, useEffect } from 'react';
function MyComponent({ reset }) {
const [counter, setCounter] = useState(0);
// Mimicking getDerivedStateFromProps
useEffect(() => {
if (reset) {
setCounter(0);
}
}, [reset]);
// ComponentDidMount equivalent
useEffect(() => {
console.log('Component has been mounted');
// ComponentWillUnmount equivalent
return () => {
console.log('Component is being unmounted');
};
}, []); // Empty dependency array ensures this runs only once
// ComponentDidUpdate equivalent
useEffect(() => {
console.log('Counter has been updated:', counter);
}, [counter]); // Runs whenever counter changes
const increment = () => {
setCounter(counter + 1);
};
return (
<div>
<p>Counter: {counter}</p>
<button onClick={increment}>Increment</button>
</div>
);
}
export default MyComponent;
Summary of Lifecycle Hooks
- Mounting Phase:
useEffect
with an empty dependency array ([]
). - Updating Phase:
useEffect
with specific dependencies ([dep1
,dep2
]). - Unmounting Phase: Return a cleanup function from
useEffect
.
By using hooks, you can achieve the same lifecycle functionalities in a more concise and modular way compared to class components.
=============================+ Thank You !!!+==============================
Note: Don’t forget to follow and give 50 claps.👏 👏 👏