What About Coding
By himanshu123Reactjs

React JS Lifecycle

React Class Component Lifecycle Methods

Every React class component moves through a lifecycle made up of four phases:

  1. Mounting
  2. Updating
  3. Unmounting
  4. Error Handling

1. Mounting

This is the phase where a component instance is created and inserted into the DOM.

import React from "react";

class Profile extends React.Component {
  constructor(props) {
    super(props);
    console.log("1: constructor");
  }

  static getDerivedStateFromProps(props, state) {
    console.log("2: getDerivedStateFromProps");
    return null;
  }

  render() {
    console.log("3: render");
    return <h1>{this.props.rollNumber}</h1>;
  }

  componentDidMount() {
    console.log("4: componentDidMount");
  }
}

export default Profile;

Call order and purpose:

  • constructor(props) โ€” always runs first, before the component ever reaches the DOM. Use it for initial setup, like setting default state.
  • static getDerivedStateFromProps(props, state) โ€” added as a replacement for the older componentWillReceiveProps. It receives the incoming props and current state and lets the component derive updated internal state from prop changes. It's called on every props/state change, but it's used rarely in practice โ€” mainly when state needs to be adjusted before the component even renders.

Example of state being altered via getDerivedStateFromProps before mount:

import React from "react";

class Profile extends React.Component {
  constructor(props) {
    super(props);
    this.state = { age: 24 };
  }

  static getDerivedStateFromProps(props, state) {
    return { age: 25 }; // overrides state before first render
  }

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

  render() {
    return (
      <>
        <h1>{this.state.age}</h1>
        <button onClick={this.increment}>Click me</button>
      </>
    );
  }
}

export default Profile;

Here, age becomes 25 before the component ever appears on screen, overriding the constructor's initial value of 24.

  • render() โ€” the only method truly required in a class component. It returns the JSX to display, can return null/booleans if nothing should render, and must behave as a pure function (no side effects, same output for same input).
  • componentDidMount() โ€” fires right after the component has been inserted into the DOM. Good place for data fetching, subscriptions, or direct DOM interaction.

Note: whenever props or state change, getDerivedStateFromProps() and render() both run again.

2. Updating

Any change to state or props causes the component to re-render โ€” this is the "updating" phase. The methods run in this order:

  • getDerivedStateFromProps() โ€” same method from mounting, also invoked before every re-render. Rarely used for updates specifically.
  • shouldComponentUpdate(nextProps, nextState) โ€” lets you compare current props/state against the incoming ones and return true or false to control whether the component re-renders at all. Mostly a performance-optimization hook, and used sparingly.
import React from "react";

class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = { age: 24 };
  }

  static getDerivedStateFromProps(props, state) {
    console.log("1: getDerivedStateFromProps");
    return null;
  }

  shouldComponentUpdate() {
    console.log("2: shouldComponentUpdate");
    return true; // false/null would block the re-render
  }

  componentDidMount() {
    console.log("componentDidMount");
  }

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

  render() {
    console.log("3: render");
    return (
      <>
        <h1>{this.state.age}</h1>
        <button onClick={this.increment}>Click me</button>
      </>
    );
  }
}

export default Counter;
  • render() runs right after shouldComponentUpdate, assuming it returned true (the default).
  • getSnapshotBeforeUpdate(prevProps, prevState) โ€” fires right before the freshly-rendered output is committed to the actual DOM. It captures information from the DOM (e.g. scroll position) as it existed just before the update, even though render already ran. It's rarely used, and whatever it returns gets passed along as the third argument to componentDidUpdate. It only makes sense paired with componentDidUpdate โ€” it isn't useful on its own.
  • componentDidUpdate(prevProps, prevState, snapshot) โ€” runs after getSnapshotBeforeUpdate, once per completed re-render. This is a common place to run side effects like network requests โ€” typically after comparing old vs. new props to decide whether a request is actually needed.

Putting all five update-phase methods together:

import React from "react";

class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = { age: 24 };
  }

  static getDerivedStateFromProps(props, state) {
    console.log("1: getDerivedStateFromProps");
    return null;
  }

  shouldComponentUpdate() {
    console.log("2: shouldComponentUpdate");
    return true;
  }

  componentDidMount() {
    console.log("componentDidMount");
  }

  getSnapshotBeforeUpdate() {
    console.log("4: getSnapshotBeforeUpdate");
    return null;
  }

  componentDidUpdate() {
    console.log("5: componentDidUpdate");
  }

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

  render() {
    console.log("3: render");
    return (
      <>
        <h1>{this.state.age}</h1>
        <button onClick={this.increment}>Click me</button>
      </>
    );
  }
}

export default Counter;

3. Unmounting

componentWillUnmount() fires right before a component is removed from the DOM and torn down โ€” the standard place to clean up timers, subscriptions, or event listeners.

4. Error Handling

These methods trigger when a descendant (child) component throws an error:

  • static getDerivedStateFromError(error) โ€” called first, receiving the thrown error, so the component can update its state to show a fallback UI.
  • componentDidCatch(error, info) โ€” called after the error occurs too, but additionally receives an info object with more detail about where the error came from (e.g. component stack). Commonly used for logging.
import React, { Component } from "react";

class ErrorBoundary extends Component {
  state = { hasError: false };

  static getDerivedStateFromError(error) {
    console.log(`Caught in getDerivedStateFromError: ${error}`);
    return { hasError: true };
  }

  componentDidCatch(error, info) {
    console.log(`Caught in componentDidCatch: ${error}`);
    console.log(info);
  }

  render() {
    if (this.state.hasError) {
      return <h2>Something went wrong.</h2>;
    }
    return this.props.children;
  }
}

export default ErrorBoundary;

Share

More recent posts

View all