We all know that everything that exists in this world has a cycle in their life. As humans, in our life cycle, we are born, grow up, and finally, die. So as React components they get initialized, updated and then die. This process is known as the React component lifecycle. Each component maintains a cycle from when it is generated and mounted on the DOM to when it is unmounted and destroyed.
React offers hooks, methods that are automatically called at each stage in the life cycle, giving you good control over what happens at the stage at which it is invoked. Strong awareness of these hooks will give us the freedom to easily manipulate what is happening in a component throughout its entire life.
The lifecycle of a component is divided generally into four parts:
- Mounting
- Updating
- Unmounting
Let’s explore the various lifecycle methods applicable at these different stages.
Mounting Phase
A component mounts when it is created inside a constructor with props and state initialized and first placed in the DOM, that is when it is rendered for the first time. In this phase, these methods shall apply:
- constructor()
- getDerivedStateFromProps()
- componentWillMount()
- render()
- componentDidMount()
The constructor()
This is the first method for which every item is named. Initializing the props and state is the main objective of the constructor. In addition, it also links the events to “this”. A call to the super() is included in the constructor together with the initialization of “this.state”. Another point to remember is that the state initialization can also be performed without the constructor() and it will behave the same.
import React from ‘react’;class FriendsComponent extends React.Component { constructor(props) { super(props); this.state = { title : ‘F.R.I.E.N.D.S’ } console.log(‘Saying Hi from the Constructor’); } }
The getDerivedStateFromProps()
The GetDerivedStateFromProps method is called just before rendering the component on the DOM. When the state of the component relies on the props, this method is called. Generally, whenever there is some change in the props, this method enables the component to adjust its state. This is quite seldom used, but the order of execution is crucial to grasp since this method is named in both the Mounting Phase and the Updating Phase.
Proceeding with the code snippet above:
import React from ‘react’; class FriendsComponent extends React.Component { constructor(props) { super(props); this.state = { title : ‘F.R.I.E.N.D.S.’ } console.log(‘Saying Hi from the Constructor’); }static getDerivedStateFromProps(props, state) { console.log(‘Saying Hi in the React Component getDerivedStateFromProps’); } }
The componentWillMount()
The componentWillMount() method will be invoked just before a component mounts or the render() method is invoked. The reality is that in your React application, you could barely make use of this method. Let me tell you why.
The componentWillMount() resides, between both the constructor and the render(), which puts it in a rather odd place. For a component, it can be used to set the default configuration as it is prior to the render method, but this is often done using the constructor. Though between these two methods nothing varies, there would be no need to establish the configuration again.
Now you may assume this is the best location to make client-side rendering API calls, but it must not be done here. API calls are asynchronous, and before the render() gets called, the data may not have been returned. So with the DOM (i.e. updating the data with API response), nothing can be done as it has not been mounted. This implies the component can be rendered at least once with empty data.
A nice way to use this method would then be to carry out any setup that can be accomplished at runtime, such as connecting to external APIs like Firebase. This configuration, like your root component, can usually be performed at the top level of your component, so most of the components will probably not use this method.
class FriendsComponent extends React.Component { componentWillMount() { console.log(‘Hello I am Chandler Bing’); }render() { return <h1>Hello Friends</h1>; } }
The render() method
Most used lifecycle method is the render() method. In all of the React groups, you’ll see it. That’s because render() is the only method needed within a class component. As the name implies It manages the rendering of the component to the user interface. This occurs in your component mounting and upgrading phase.
This method does not change the state; each time it is invoked, it literally returns the same result. The render() method monitors the values of the props and state and returns any of the following:
- React Element
- Array
- Fragment
- Strings, numbers, booleans or null
class FriendsComponent extends Component{
render(){
return <div>Hi Chandler {this.props.name}</div>
}
}
The componentDidMount() method
Just after the component is mounted, this method becomes accessible. That’s after the rendered HTML completed loading. In the component life cycle, this is invoked only once and it means that the component and all its sub-components have been correctly rendered. Within this method, you could also call the setState() method to change the state and eventually recall the render() method to update the DOM. Even if the render() function is called twice, this method guarantees that the user will not see any intermediary states.
So this really is the safest place to make API calls since the component has been mounted and is accessible to the DOM at this stage. ComponentDidMount is generally a good place to do all the configuration without the DOM that you couldn’t have done. Here are a lot of things that you would do with this method:
- Connect a React app to external apps, such as JavaScript frameworks or web APIs.
- Using SetTimeout or SetInterval to set timers.
- Add listeners for events.
- Draw on an element that has just been rendered.
import React from ‘react’;class FriendsComponent extends React.Component { constructor(props) { super(props); this.state = { title : ‘F.R.I.E.N.D.S’ } console.log(‘Saying Hi from the Constructor’); }static getDerivedStateFromProps(props, state) { console.log(‘Saying Hi in the React Component getDerivedStateFromProps’); }componentDidMount(){ console.log(“Hi Friends componentDidMount”); }render() { console.log(‘Hi Friends I am in the render method’); return <div> This is the FriendsComponent </div> } }
Updating Phase
After mounting, components do not always stay in the same condition. The underlying props might often change and it is appropriate to re-render the component. The lifecycle methods for updating give you authority over when and how this update should actually occur.
There are a total of 5 methods in the update phase, including these methods.
- componentWillReceiveProps()
- shouldComponentUpdate()
- componentWillUpdate()
- render()
- componentDidUpdate()
The componentWillReceiveProps() method
Props are passed to a component from its parent component externally. These props are often hooked to the parent component state. So if the parent component’s state changes, the props have changed to the component state, and it needs to be revised. If the props are linked with the component state, a shift would imply a shift in the component state.
ComponentWillReceiveProps is a method named before the new props do something for a component. This method is called using new props as arguments. Here, the next set of props and the current ones are available for us to access. Therefore we can compare the current props with the newer ones using this method and assess if something has really varied.
class FriendsComponent extends React.Component { constructor(props) { super(props); this.state = {name: this.props.name}; }componentWillReceiveProps(nextProps) { if (this.props.name !== nextProps.name) { this.setState({name: nextProps.name}); } }render() { return ( <h1>{this.state.name}</h1> ) } }
“this.state.name” will be changed in the illustration above only if the current name is different from the prior one. But the state is not changed if there’s no difference.
The shouldComponentUpdate() method
Before the component render again after getting a newer collection of props or there is a new state, this method will be called. We could see that two arguments, the next props, and the next state are received. The usual behaviour of this method is for a component to rerender once the state of the props has changed.
shouldComponentUpdate() can be used to allow React to know that the performance of a component is not impacted by a modification in the component props or state and should therefore not be re-rendered. If, either a true or a false value is returned the component will go forward and do what it always does, re-render the component if it returns true. If it returns false, then it will not update the component. Notice that it does not stop the child components re-rendering when their state changes.
The simplest approach to use this method is to make it return false and then under some circumstances, the component will not update. If the circumstances are met, it will not update the component.
The component can only update if the new input is different than the prior one.
class FriendsComponent extends React.Component { […] shouldComponentUpdate(nextProps, nextState) { if (this.state.name == nextState.name) { console.log(“Inside shouldComponentUpdate”); return false; } } […] }
The componentWillUpdate() method
ComponentWillUpdate is the method which can be used before re-rendering occurs to do the preparations. This method does not allow you to call this.setState.
With this method, one important thing to be done is to communicate with stuff outside of the React architecture. ComponentWillUpdate may also be used if you need to perform some non-React set up prior to a component render.
If you are using shouldComponentUpdate, another time to use this method is when you need to do stuff whenever the props change. It is better to use it instead of ComponentWillReceiveProps in this case because it will only be invoked when the component is actually re-rendered. However, always use ComponentWillReceiveProps instead if you need to change the state in relation to a change in props.
Although it can be used to achieve animations and other effects, it should never be done because before the component is actually re-rendered, this method could be called several times.
The syntax is as follows:
class FriendsComponent extends React.Component { […]componentWillUpdate(nextProps, nextState) { // Do something here } […] }
The componentDidUpdate() method
After the rendered HTML has completed loading, componentDidUpdate is invoked. Before the current update process starts, it gets two arguments, the props and status of the component.
The perfect spot for communicating with a non-React environment such as the browser or making HTTP requests in componentDidUpdate. To stop unwanted network requests, it should be achieved when you evaluate the new props with the previous props.
An illustration of using componentDidUpdate is shown below.
class FriendsComponent extends React.Component { […] componentDidUpdate(prevProps, prevState) { if (this.props.name == prevProps.name) { // make ajax calls // Perform any other function } } […] }
An example of an updating phase is as follows.
Child.js
import React, { Component } from ‘react’; class ChildFriendsComponent extends Component{ constructor(props){ super(props); this.state={ value:’FRIENDS’ } console.log(“Hi you’re in the child constructor”); } static getDerivedStateFromProps(props,state){ console.log(“Hi you’re in the child getDerivedStateFromProps”); return null; } componentDidMount(){ console.log(“Hi you’re in the child componentDidMount”); } shouldComponentUpdate(){ console.log(“Hi you’re in the child shouldComponentUpdate”); return true; } getSnapshotBeforeUpdate(prevProps,prevState){ console.log(“Hi you’re in the child getSnapshotBeforeUpdate”); return null; } componentDidUpdate(){ console.log(“Hi you’re in the child componentDidUpdate”); } render(){ console.log(“Hi you’re in the Friends Child Component render”); return <div/> } } export default ChildFriendsComponent ;
App.js
import React,{Component} from ‘react’; import ChildFriendsComponent from ‘./Child’; class FriendsComponent extends Component{ constructor(props){ super(props); this.state={ value:FRIENDS’ } this.changeState = this.changeState.bind(this); console.log(“Hi you’re in the constructor”); } static getDerivedStateFromProps(props,state){ console.log(“Hi you’re in the getDerivedStateFromProps”); return null; } componentDidMount(){ console.log(“Hi you’re in the componentDidMount”); } shouldComponentUpdate(){ console.log(“Hi you’re in the shouldComponentUpdate”); return true; } getSnapshotBeforeUpdate(prevProps,prevState){ console.log(“Hi you’re in the getSnapshotBeforeUpdate”); return null; }componentDidUpdate(){ console.log(“Hi you’re in the componentDidUpdate”); } changeState = () => { this.setState({ value : “FRIENDS started” }) } render(){ console.log(“Hi you’re in the render”); return( <div> <div>Friends Parent Component</div> <button onClick={this.changeState}>Say Hi</button> <ChildFriendsComponent/> </div> ); } } export default FriendsComponent ;
Unmounting Phase
Components will not always persist in the DOM. Perhaps, due to state changes or something else, they have to be discarded. The method of unmounting will assist us in managing the unmounting of components. We say method because as in React 16, there is only one method for unmounting.
The componentWillUnmount() method
This is the only unmounting technique. ComponentWillUnmount is called immediately before removing a component from the DOM. It is where any cleanups that should be performed, such as invalidating timers, suspending network requests, deleting event listeners, or suspending any componentDidMount subscriptions.
The componentWillUnmount() is the last stage of any React Component’s lifecycle, which can never be mounted again after it is unmounted. And the setState() method would re-render the DOM contents, so it won’t be possible to do so.
class FriendsComponent extends React.Component { […]componentWillUnmount() { document.removeEventListener(“click”, SomeFunction); `}[…]}
Lifecycle methods or Lifecycle hooks in functional component
There is no component lifecycle method in the functional component since a functional component is just a JavaScript function, we can not use the setState() method within the component. That’s why they are often called stateless functional components.
In functional components, we can use React Hooks, useEffect() hook can be used to replicate lifecycle actions, and useState can be used in a functional component to store status.
Conclusion
Drilling a little further, any time something interesting happens, we find that React continuously watches and notifies our components. Much of this is achieved by the lifecycle methods that we focused on throughout this article.
The lifecycle methods we discussed here are the common ones you would almost always end up using. For some unusual and complex cases, there are a handful of uncommon lifecycle methods that you will require.