o7planning

ReactJs component Lifecycle methods

  1. Component Lifecycle
  2. UNSAFE_componentWillMount()
  3. componentDidMount()
  4. componentWillReceiveProps (nextProps)
  5. shouldComponentUpdate (nextProps,nextState)
  6. UNSAFE_componentWillUpdate (nextProps,nextState)
  7. componentDidUpdate (prevProps,prevState)

1. Component Lifecycle

A range of changes that Component undergoes from its creation until it is terminated (destroyed) are called a lifecycle of the component. During the existence of the Component, methods will be called. Below is the illustration of Component lifecycle and the methods that will be called in the different stages.
version 16.3 or later, some methods in the Component lifecycle have been renamed. It adds the prefix "UNSAFE_" as a way to warn that you should be careful when you override this method, because it is often misunderstood and misused subtly. It can cause problems with "Async Rendering".

2. UNSAFE_componentWillMount()

The UNSAFE_componentWillMount method is called before the ReactJS calls the render() method to render the Component on the interface in the first time. This method can be executed in the both sides- Server and Client.
The UNSAFE_componentWillMount method gives you a chance to configure, update status, calculate values to prepare for the first rendering time. At this time, the state and props have been defined, you may safely query this.state, this.props and know their values for sure .
person.jsx
class Person extends React.Component {
  constructor(props) {
    super(props);
    this.state = { mode: undefined };
  }

  UNSAFE_componentWillMount() {
    let modeValue;
    if (this.props.age > 70) {
      modeValue = "old";
    } else if (this.props.age < 18) {
      modeValue = "young";
    } else {
      modeValue = "middle";
    }
    this.setState({ mode: modeValue });
  }

  render() {
    return (
      <div className={"person person-" + this.state.mode}>
        {this.props.name} (age: {this.props.age})
      </div>
    );
  }
}

Person.defaultProps = { age: "unknown" };

// Render
ReactDOM.render(
  <Person name="Donald Trump" age="72" />,
  document.getElementById("person1")
);
ReactDOM.render(
  <Person name="Ivanka Trump" age="36" />,
  document.getElementById("person2")
);
person.html
<!DOCTYPE html>
<html lang="en">
   <head>
      <meta charset="UTF-8">
      <title>ReactJS UNSAFE_componentWillMount()</title>
      <script src="https://unpkg.com/react@16.4.2/umd/react.production.min.js"></script>
      <script src="https://unpkg.com/react-dom@16.4.2/umd/react-dom.production.min.js"></script>
      <script src="https://unpkg.com/babel-standalone@6.26.0/babel.min.js"></script>
      <style>
         .person  {
         border:1px solid #cbbfab;
         width: 250px;
         height: 50px;
         padding: 5px;
         margin: 5px;
         }
         .person-old {
         background-color: Gray;
         }
         .person-middle {
         background-color: LightGray;
         }
         .person-young {
         background-color: white;
         }
      </style>
   </head>
   <body>
      <h1>UNSAFE_componentWillMount():</h1>

      <div id="person1"></div>
      <div id="person2"></div>

      <script src="person.jsx" type="text/babel"></script>
   </body>
</html>
Run the example:

3. componentDidMount()

The componentDidMount() method is called immediately after the Component is rendered on the interface for the first time. It is executed at the client side.
The componentDidMount() method is called when the Component has been rendered on the interface one time, therefore, in this method, you may access Native UI (DOM, UIView,..) to do something that you want. You can also call another Javascript library in this method, for example, calling to a Chart library to display the chart by data of the Component.
The componentDidMount() method can be also the place for you to use AJAX to take data from Server, and then call setState() to change the status of Component. In case of being successful, the Component will be rendered again.
Example:
OK, in this example, I simulate loading data from the Server in the componentDidMount() method.
employee.jsx
class Employe extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      loaded: false,
      empId: "[empId]",
      fullName: "[fullName]"
    };
  }

  // Load data from Server..
  loadEmployeeData() {
    setTimeout(() => {
      console.log("Data is loaded");
      this.setState({
        loaded: true,
        empId: this.props.empId,
        fullName: "Emp " + Math.random()
      });
    }, 1000);
  }

  componentDidMount() {
    this.loadEmployeeData();
  }

  render() {
    if (this.state.loaded == true) {
      return (
        <div className="employee">
          <p>Emp Id: {this.state.empId}</p>
          <p>Full Name: {this.state.fullName}</p>
        </div>
      );
    } else {
      return (
        <div className="employee">
          <p>
            Wait while data loading. EmpID: {this.props.empId}
          </p>
        </div>
      );
    }
  }
}

// Render
ReactDOM.render(<Employe empId="1" />, document.getElementById("employee1"));
employee.html
<!DOCTYPE html>
<html lang="en">
   <head>
      <meta charset="UTF-8">
      <title>ReactJS componentDidMount()</title>
      <script src="https://unpkg.com/react@16.4.2/umd/react.production.min.js"></script>
      <script src="https://unpkg.com/react-dom@16.4.2/umd/react-dom.production.min.js"></script>
      <script src="https://unpkg.com/babel-standalone@6.26.0/babel.min.js"></script>

      <style>
         .employee  {
         border:1px solid #cbbfab;
         padding: 5px;
         margin: 5px;
         }
      </style>
   </head>
   <body>
      <h1>componentDidMount():</h1>
      
      <div id="employee1"></div>

      <script src="employee.jsx" type="text/babel"></script>
   </body>
</html>
Run the employee.html file on the HTTP Server:

4. componentWillReceiveProps (nextProps)

5. shouldComponentUpdate (nextProps,nextState)

The shouldComponentUpdate() method returns true/false. It is called after the Component is established a new status through the setState() method. At the shouldComponentUpdate(), you can decide to rerender or not rerender the Component on the interface.
  • If the method returns true, theComponent will be re-rendered on the interface.
  • If the method returns false, nothing will be done next.
odd-number.jsx
class NumberView extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      currentNumber: 1
    };
  }

  nextValue() {
    this.setState((prevState, props) => {
      return {
        currentNumber: prevState.currentNumber + 1
      };
    });
  }

  shouldComponentUpdate(nextProps, nextState) {
    // Odd Number
    return nextState.currentNumber % 2 == 1;
  }

  render() {
    return (
      <div className="number-viewer">
        <button onClick={() => this.nextValue()}>Next Value</button>
        <p>Current Value: {this.state.currentNumber}</p>
      </div>
    );
  }
}

// Render
ReactDOM.render(<NumberView />, document.getElementById("numberview1"));
odd-number.html
<!DOCTYPE html>
<html lang="en">
   <head>
      <meta charset="UTF-8">
      <title>ReactJS shouldComponentUpdate()</title>
      <script src="https://unpkg.com/react@16.4.2/umd/react.production.min.js"></script>
      <script src="https://unpkg.com/react-dom@16.4.2/umd/react-dom.production.min.js"></script>
      <script src="https://unpkg.com/babel-standalone@6.26.0/babel.min.js"></script>

      <style>
         .number-view  {
         border:1px solid #cbbfab;
         padding: 5px;
         margin: 5px;
         }
      </style>
   </head>
   <body>
      <h1>shouldComponentUpdate():</h1>

      <p>Show only odd numbers</p>
      <div id="numberview1"></div>

      <script src="odd-number.jsx" type="text/babel"></script>
   </body>
</html>

6. UNSAFE_componentWillUpdate (nextProps,nextState)

The UNSAFE_componentWillUpdate(nextProps,nextState) method is the place allowing configuring or calculating values before the Component is re-rendered. This method is quite like the UNSAFE_componentWillMount(). The difference in this method is that you can visit next statuses of the Component through the nextState parameter.
Note: In the UNSAFE_componentWillUpdate(nextProps,nextState) method, you mustn't call the setState(), because it can create an endless loop.
revenue.jsx
class RevenueView extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      year: 2018,
      revenue: 1000,
      growthRate: "Unknown"
    };
  }

  nextYear() {
    this.setState((prevState, props) => {
      var randomRevenue = prevState.revenue * (1 + Math.random());
      return {
        year: prevState.year + 1,
        revenue: randomRevenue
      };
    });
  }

  UNSAFE_componentWillUpdate(nextProps, nextState) {
    var rate = (nextState.revenue - this.state.revenue) / this.state.revenue;
    nextState.growthRate = 100 * rate + " %";
  }

  render() {
    return (
      <div className="revenue-view">
        <p>Year: {this.state.year}</p>
        <p>Revenue: {this.state.revenue}</p>
        <p>Growth Rate: {this.state.growthRate}</p>
        <button onClick={() => this.nextYear()}>Next Year</button>
      </div>
    );
  }
}

// Render
ReactDOM.render(<RevenueView />, document.getElementById("revenueview1"));
revenue.html
<!DOCTYPE html>
<html lang="en">
   <head>
      <meta charset="UTF-8">
      <title>ReactJS UNSAFE_componentWillUpdate(props,nextState)</title>
      <script src="https://unpkg.com/react@16.4.2/umd/react.production.min.js"></script>
      <script src="https://unpkg.com/react-dom@16.4.2/umd/react-dom.production.min.js"></script>
      <script src="https://unpkg.com/babel-standalone@6.26.0/babel.min.js"></script>

      <style>
         .revenue-view  {
         border:1px solid #cbbfab;
         padding: 5px;
         margin: 5px;
         }
      </style>
   </head>
   <body>
      <h3>UNSAFE_componentWillUpdate(nextProps,nextState):</h3>

      <div id="revenueview1"></div>

      <script src="revenue.jsx" type="text/babel"></script>
   </body>
</html>

7. componentDidUpdate (prevProps,prevState)

  • TODO !!