React Lifecycle with Class and Hooks: 2024

Deepak Chaudhari
4 min read3 days ago

--

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:

Figure 1.0.0

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 or false.
  • 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.👏 👏 👏

--

--