Posted

6 minutes read

Definition of component lifecycle

The React component lifecycle represents the flow of events which a React component goes through during its lifetime. For more details about components types or an in-depth explanation of React components.

Major changes to the React component lifecycle were added with ReactJS 16.3.
Some lifecycle methods have been deprecated while new methods were added.
In this post we will focus on the methods from version 16.3+.

Phases of the component lifecycle

  • Mounting
  • Updating
  • Unmounting

React component lifecycle diagram

React lifecycle methods

Lifecycle methods are various methods which are invoked at different phases of the lifecycle of a component.

React lifecycle method call order by phase

Mounting

Mounting refers to the loading of components in the DOM.
The methods that get called during initialisation and loading of the component on to the DOM are listed in the order they get called below.

  • constructor
  • static getDerivedStateFromProps
  • render
  • componentDidMount

Updating

  • static getDerivedStateFromProps
  • shouldComponentUpdate
  • render
  • getSnapshotBeforeUpdate
  • componentDidUpdate

Unmounting

  • componentWillUnmount

React common lifecycle methods

constructor(props)

The constructor represents the first method that gets called when a component is created.
The constructor is only called once in the entire lifecycle of the component.

Usage

  • set up the initial local state of the component by assigning to the this.state
  • binding event handler methods to the instance

Example of using a constructor in a class component


import React, { Component } from 'react';

class LoginBar extends Component{

	constructor(props){
		super(props);
		console.log('The constructor called')	

		this.state = {
			userType: 'basic'
		}
		this.handleClick = this.handleClick.bind(this);
	}
	
	handleClick(){
		this.setState({userType: 'pro'});
	}
	
	render(){
		return(
			<div>
				<h1> Logged in as {this.props.username} type {this.state.userType}</h1>
				<button onClick={this.handleClick}>Change user type</button>		
			</div>			
		);
	}
}

export default LoginBar;

Warning: Remember to first call in the constructor the super constructor passing the props as arguments (super(props) as above)
otherwise the this.props will be undefined in the constructor.

In the case that you do not initialise the state or you don’t need to bind event handlers then you do not need to implement a constructor.

render()

The render() method is the only method required in a React component.

The method handles the rendering of the component in the UI. This happens during the mount and update of the component.

The render() method should do the following:

  • examine this.props and this.state
  • return one of the following
    • an element which can be either e DOM element or another user defined component element
    • arrays and fragments: array of elements to be rendered using React.fragment
    • a portal: basically a way of inserting children elements in DOM nodes outside the DOM hierarchy of the parent component
    • strings and numbers: will be rendered as text nodes in the DOM
    • boolean or null: render nothing

The render method is a pure function, which means that for the same input it should return the same output.
The state of the component should not be changed inside the render function.

The render method will not be invoked if the the shouldComponentUpdate() lifecycle method returns false.

Example of a basic render method returning an element defined using JSX


import React, { Component } from 'react';

class LoginBar extends Component{

	
	render(){
		return(
			<h1> Logged in as {this.props.username}</h1>
		);
	}
}

export default LoginBar;

Example of a render method returning a React fragment


import React, { Component } from 'react';

class LoginBar extends Component{

	constructor(props){
		super(props);
		console.log('The constructor called')	

		this.state = {
			userType: 'basic'
		}
		this.handleClick = this.handleClick.bind(this);
	}
	
	handleClick(){
		this.setState({userType: 'pro'});
	}
	
	render(){
		return(
			<React.Fragment>
				<h1> Logged in as {this.props.username} type {this.state.userType}</h1>
				<button onClick={this.handleClick}>Change user type</button>		
			</React.Fragment>			
		);
	}
}

export default LoginBar;

Example of a render method returning a portal


import React, { Component } from 'react';
import ReactDOM from 'react-dom';

class LoginBar extends Component{

	constructor(props){
		super(props);
		console.log('The constructor called')	

		this.state = {
			userType: 'basic'
		}
		this.handleClick = this.handleClick.bind(this);
	}
	
	handleClick(){
		this.setState({userType: 'pro'});
	}
	
	render(){
		return ReactDOM.createPortal(
			<React.Fragment>
				<h1> Logged in as {this.props.username} type {this.state.userType}</h1>
				<button onClick={this.handleClick}>Change user type</button>		
			</React.Fragment>,
			document.getElementById('modal-root')			
		);
	}
}

export default LoginBar;

Example of a render method returning a string or a number


import React, { Component } from 'react';

class LoginBar extends Component{

	constructor(props){
		super(props);
		console.log('The constructor called')	

		this.state = {
			userType: 'basic'
		}
		this.handleClick = this.handleClick.bind(this);
	}
	
	handleClick(){
		this.setState({userType: 'pro'});
	}
	
	render(){
		return 'Hello World!';		
	}
}

export default LoginBar;

Example of a render method returning null



import React, { Component } from 'react';

class LoginBar extends Component{

	constructor(props){
		super(props);
		console.log('The constructor called')	

		this.state = {
			userType: 'basic'
		}
		this.handleClick = this.handleClick.bind(this);
	}
	
	handleClick(){
		this.setState({userType: 'pro'});
	}
	
	render(){
		return null;		
	}
}

export default LoginBar;

componentDidMount()

The componentDidMount method is called right after the component has been mounted/inserted in the tree and is ready to use.

Usage

  • this method can be used if we need to make external API calls, if we need to retrieve data from our microservices or from third party end points
  • can be used for any initialisation that needs DOM nodes to be there
  • this method is a good place to set up subscriptions (need to remember to unsubscribe in the componentWillUnmount method)

Inside the componentDidMount the setState can be called immediately which will trigger an extra rendering but this will happen before the browser updates the screen, which means the user will not see the intermediate state. Use this pattern carefully as it may cause performance issues.

Example of using the componentDidMount()


import React, { Component } from 'react';

class LoginBar extends Component{

	constructor(props){
		super(props);
		console.log('The constructor called')	

		this.state = {
			userType: 'basic'
		}
	}
	
	componentDidMount(){	
		console.log('The method componentDidMount called');	
		this.setState({userType: 'pro'});		
	}

	render(){
		return(
			<h1> Logged in as {this.props.username} type {this.state.userType}</h1>
		);
	}
}

export default LoginBar;

componentDidUpdate(prevProps, prevState, snapshot)

The componentDidUpdate method is called as soon as the component has been updated. This method is not called for the initial render.

Usage

  • the most common use of this method is for updating the DOM in case the state or props have changed
  • a good place to make network requests as long as we do not forget to compare the current props with the previous props

Example of using componentDidUpdate


import React, { Component } from 'react';

class LoginBar extends Component{

	constructor(props){
		super(props);
		console.log('The constructor called')	

		this.state = {
			userType: 'basic'
		}
	}
	
	componentDidMount(){	
		console.log('The method componentDidMount called');	
		this.setState({userType: 'pro'});		
	}

	componentDidUpdate(prevProps, prevState){
		console.log('The method componentDidUpdate called');
		if (this.state.userType !== prevState.userType){
			this.setState({userType: 'enterprise'});		
		}			
	}

	render(){
		return(
			<h1> Logged in as {this.props.username} type {this.state.userType}</h1>
		);
	}
}

export default LoginBar;

componentWillUnmount()

The componentWillUnmount method is called just before the component is unmounted and destroyed.

Usage

  • this is a good place for any cleanup that might be needed like
    • clear timers
    • cancel network requests
    • clear caches in storage
    • clean up subscriptions

In this method the setState should not be called as the component will never re-render.

React uncommon lifecycle methods

shouldComponentUpdate(nextProps, nextState)

This should be used in the case we want to tell React whether we should update and re-render or not in case of state or props changes.
By default whenever the props or state changes a re-render will happen.

The shouldComponentUpdate() method gets invoked before rendering when new props or state are being received.

This method is not called for the initial rendering or when using forceUpdate() method.

This method only exists as a performance optimisation.

static getDerivedStateFromProps(props, state)

The getDerivedStateFromProps method is called just before the render method is called on every render. This is a safer method of the previous componentWillReceiveProps.
This is a static method that does not have access to “this”. The method returns an object to update the state in response to prop changes. It can however return null in case no changes to the state are necessary.

This method is used in the rare cases where the state depends on changes to the props.

getSnapshotBeforeUpdate(prevProps, prevState)

The getSnapshotBeforeUpdate method is called right before the DOM is updated. The value that is returned from getSnapshotBeforeUpdate() is passed on to componentDidUpdate().

Usage

  • resizing the window during an async rendering is a good use-case of when the getSnapshotBeforeUpdate()
  • handle scroll position in a special way

Keep in mind that this method should also be used rarely or not used at all.

.





Thanks for reading. I hope you learned something interesting about React!
If you found this article useful, please share it with others. Don’t forget to subscribe to get notified for the upcoming articles.