React Component Lifecycle and React Hooks

React components follow a lifecycle, which is a series of phases they go through during their existence in an application. These phases include Mounting, Updating, and Unmounting.

While class components use lifecycle methods to manage these phases, functional components achieve the same with React Hooks.

1. React Component Lifecycle

The lifecycle of a React component consists of three main phases:

  1. Mounting: When the component is first added to the DOM.
  2. Updating: When the component’s state or props change, causing a re-render.
  3. Unmounting: When the component is removed from the DOM.

Lifecycle Methods in Class Components

PhaseMethodDescription
Mountingconstructor()Initializes state and binds methods.
 componentDidMount()Executes after the component is added to the DOM.
UpdatingshouldComponentUpdate()Controls if the component should re-render.
 componentDidUpdate()Executes after the component re-renders.
UnmountingcomponentWillUnmount()Executes before the component is removed from the DOM.

Diagram: Component Lifecycle

Below is a diagram illustrating the lifecycle of a React Class Component:

+----------------------------+
|        Mounting            |
|                            |
| constructor()              |
| componentDidMount()        |
+----------------------------+
         ↓
+----------------------------+
|        Updating            |
|                            |
| shouldComponentUpdate()    |
| componentDidUpdate()       |
+----------------------------+
         ↓
+----------------------------+
|        Unmounting          |
|                            |
| componentWillUnmount()     |
+----------------------------+

Example: Lifecycle Methods in Class Components

import React, { Component } from 'react';

class LifecycleExample extends Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
    console.log("Constructor: Component is initialized");
  }

  componentDidMount() {
    console.log("ComponentDidMount: Component added to the DOM");
  }

  componentDidUpdate(prevProps, prevState) {
    console.log("ComponentDidUpdate: Component re-rendered");
  }

  componentWillUnmount() {
    console.log("ComponentWillUnmount: Component is about to be removed");
  }

  increment = () => {
    this.setState({ count: this.state.count + 1 });
  };

  render() {
    return (
      <div>
        <h1>Count: {this.state.count}</h1>
        <button onClick={this.increment}>Increment</button>
      </div>
    );
  }
}

export default LifecycleExample;

2. React Hooks: useState and useEffect

React Hooks provide a way to use state and lifecycle features in functional components.

a. useState

The useState Hook allows you to add state to functional components.

Syntax:

const [state, setState] = useState(initialValue);

Example: Using useState

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

export default Counter;

b. useEffect

The useEffect Hook allows you to perform side effects (e.g., fetching data, updating the DOM) in functional components.

Syntax:

useEffect(() => {
  // Side effect code here
  return () => {
    // Cleanup code here (optional)
  };
}, [dependencies]);

Example: Using useEffect

import React, { useState, useEffect } from 'react';

function Timer() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log("Effect: Component rendered or updated");
    const interval = setInterval(() => setCount((prev) => prev + 1), 1000);

    // Cleanup function
    return () => {
      clearInterval(interval);
      console.log("Cleanup: Timer stopped");
    };
  }, []);

  return <h1>Timer: {count}s</h1>;
}

export default Timer;

Diagram: useEffect Flow

+-------------------------------+
|    Component Renders          |
|-------------------------------|
|    useEffect Runs             |
|    (Side Effect Code)         |
+-------------------------------+
         ↓
+-------------------------------+
| Component Updated (if deps)   |
|-------------------------------|
|    useEffect Runs Again       |
|    (Optional Cleanup)         |
+-------------------------------+
         ↓
+-------------------------------+
| Component Unmounted           |
|-------------------------------|
|    Cleanup Runs               |
+-------------------------------+

Comparison: Class Lifecycle Methods vs Hooks

Lifecycle MethodReact Hook
componentDidMountuseEffect (no deps)
componentDidUpdateuseEffect (with deps)
componentWillUnmountCleanup in useEffect

Best Practices for React Lifecycle and Hooks

  • Keep Side Effects in useEffect: Avoid performing side effects directly in the render method.
  • Use Cleanup Functions: Always clean up resources in useEffect to avoid memory leaks.
  • Optimize State Updates: Use functional updates (setState(prev => ...)) to avoid stale state issues.