Introduction
In this
previous article, we learned about React forms along with controlled and uncontrolled components in React. In this article we will learn about component lifecyle along with its phases and how it works in React.
Components Life Cycle
Every React component has it own lifecycle. The lifecycle of the component is defined by the sequence of methods executed in different stages of the component’s existence.
React has 4 phases of component:
Mounting
This is the very first stage where component is created with props and state.
This all is done within constructor. After getting ready with state and props, our component is ready to mount on the DOM and it is rendered for the first time on the web page.
This phase has 4 methods in it:
constructor()
The constructor of component method is called before every other method is called.
The main purpose of this method is to initialize props and state and to bind event handlers to the instance. In the constructor do not use any side effects like HTTP request.
Syntax - constructor(props)
Constructor include super(props) as its first statement followed by initialization of this.state, it directly overwrites this.state method.
static getDerivedStateFromProps()
This method is called just before render() method is called. This method is used when the state of the component depends on props. This method is called just before render method both on initial mount or subsequent requests. In this method we can set the state.
In this method, likewise in constructor, do not use any side effect for eg. HTTP request etc.
Syntax - static getDerivedStateFromProps(props,state)
This method enables a component to update its internal state as a result of changes in props. This method is used in very rare cases as the method does not have access to class instance.
render()
This method is the only required method in the class component.The render() function does not modify state component. It returns the same result each time its invoked, but this method does not directly interact with the browser.
Syntax - render()
While calling this method it observes this.props() and this.state() value and returns one of the following types like: React elements, array, fragments, string and numbers, booleans or null.
componentDidMount()
componentDidMount() is called just after component is mounted (inserted into the tree). If it is required to load data from remote endpoint this method is the best place to instantiate a network request. In this method setState() method can be called.
This method will call an extra rendering but all this happens before the browser updates the screen.This method ensures that the user won't see any intermediate states even though render() method is called twice.
Syntax - componentDidMount()
This method causes side effects like Http request, any endpoint request or interacting with DOM.
Let’s look at an example.
Create a class named Lifecycle.js
- import React,{Component} from 'react';
-
- class Lifecycle extends Component{
- constructor(props){
- super(props);
- this.state={
- value:'React Application'
- }
- console.log("React Application constructor");
- }
-
- static getDerivedStateFromProps(props,state){
- console.log("React Application getDerivedStateFromProps");
- return null;
- }
-
- componentDidMount(){
- console.log("React Application componentDidMount");
- }
-
- render(){
- return <div/>
- }
- }
-
- export default Lifecycle;
The output will display as below,
Now create a child component name LifecycleChild.js
- import React,{Component} from 'react';
-
- class LifecycleChild extends Component{
- constructor(props){
- super(props);
- this.state={
- value:'React Application'
- }
- console.log("React Application child constructor");
- }
-
- static getDerivedStateFromProps(props,state){
- console.log("React Application child getDerivedStateFromProps");
- return null;
- }
-
- componentDidMount(){
- console.log("React Application child componentDidMount");
- }
-
- render(){
- console.log("React Application child render");
- return <div/>
- }
- }
-
- export default LifecycleChild;
Update Lifecycle.js
- import React,{Component} from 'react';
- import LifecycleChild from './LifecycleChild';
-
- class Lifecycle extends Component{
- constructor(props){
- super(props);
- this.state={
- value:'React Application'
- }
- console.log("React Application constructor");
- }
-
- static getDerivedStateFromProps(props,state){
- console.log("React Application getDerivedStateFromProps");
- return null;
- }
-
- componentDidMount(){
- console.log("React Application componentDidMount");
- }
-
- render(){
- console.log("React Application render");
- return(
- <div>
- <div>Lifecycle Parent</div>
- <LifecycleChild></LifecycleChild>
- </div>
- );
- }
- }
-
- export default Lifecycle;
The output will be displayed as below,
After calling render method of parent component, child component starts its execution.
Updating
When the component needs to be re-rendered due to changes in either state or props.
This phase has 5 methods,
static getDerivedStateFromProps()
This method is called every time the component is re-rendered.
The main thing is do not cause any side effects in it; i.e., no Http requests, no Ajax calls etc.
Syntax - getDerivedStateFromProps(state,props)
shouldComponentUpdate()
This method re-renders on every state change.This method defines if the component should be re-rendered or not. This method provides performance optimization. shouldComponentUpdate() method is invoked before rendering when new props or state are recieved. This method is not called on initial render and also when forceUpdate() method is called.
Syntax - shouldComponentUpdate(nextProps,nextState)
Here, if you are pretty sure about the code you are writing then you can consider nextProps as this.props and nextState as this.state which return false notifying React that update can be skipped.
When returning false, it does not stop it from re-rendering component when state changes.
render()
This method is the only required method in React class component. This method reads state and props which in return provides JSX.
Syntax - render()
This method does not change any value of props and state or make any interact with DOM or make any ajax calls.
getSnapshotBeforeUpdate()
This method is called just before any changes are going to be updated in Real DOM from virtual DOM. This method is used to capture some information from DOM just like observing scroll position. This method provides a final call to check our data with its previous state and props. If it is required to know the exact DOM available just before updating the result of latest render call.
Syntax - getSnapshotBeforeUpdate(prevProps,prevState)
This method will either return null or return a value. When returning a value it will be passed as the third parameter to the next method.
componentDidUpdate()
This method is called after all the changes are updated in the DOM.
Syntax - componentDidUpdate (prevProps,prevState,snapShot).
This method accepts 3 parameters: previous props, previous state and the value that is returned by getSnapshotBeforeUpdate or null.
Now look at the demo for example and execution of updating methods in LifecycleChild.js,
- import React,{Component} from 'react';
-
- class LifecycleChild extends Component{
- constructor(props){
- super(props);
- this.state={
- value:'React Application'
- }
- console.log("React Application child constructor");
- }
-
- static getDerivedStateFromProps(props,state){
- console.log("React Application child getDerivedStateFromProps");
- return null;
- }
-
- componentDidMount(){
- console.log("React Application child componentDidMount");
- }
-
- shouldComponentUpdate(){
- console.log("React Application child shouldComponentUpdate");
- return true;
- }
-
- getSnapshotBeforeUpdate(prevProps,prevState){
- console.log("React Application child getSnapshotBeforeUpdate");
- return null;
- }
-
- componentDidUpdate(){
- console.log("React Application child componentDidUpdate");
- }
-
- render(){
- console.log("React Application child render");
- return <div/>
- }
- }
-
- export default LifecycleChild;
And also in Lifecycle.js
- import React,{Component} from 'react';
- import LifecycleChild from './LifecycleChild';
-
- class Lifecycle extends Component{
- constructor(props){
- super(props);
- this.state={
- value:'React Application'
- }
- this.changeState = this.changeState.bind(this);
- console.log("React Application constructor");
- }
-
- static getDerivedStateFromProps(props,state){
- console.log("React Application getDerivedStateFromProps");
- return null;
- }
-
- componentDidMount(){
- console.log("React Application componentDidMount");
- }
-
- shouldComponentUpdate(){
- console.log("React Application shouldComponentUpdate");
- return true;
- }
-
- getSnapshotBeforeUpdate(prevProps,prevState){
- console.log("React Application getSnapshotBeforeUpdate");
- return null;
- }
-
- componentDidUpdate(){
- console.log("React Application componentDidUpdate");
- }
-
- changeState = () => {
- this.setState({
- value : "React Application started"
- })
- }
-
- render(){
- console.log("React Application render");
- return(
- <div>
- <div>Lifecycle Parent</div>
- <button onClick={this.changeState}>Click Me</button>
- <LifecycleChild></LifecycleChild>
- </div>
- );
- }
- }
-
- export default Lifecycle;
Now look at the output below,
Now on click of the button, review output in console,
If you closely observe the output in console you will find out that the order for all methods is as per their call but there is a slight difference in calling of getSnapshotBeforeUpdate, for this child method is called before parent method. After completion of its call all parent methods get executed.
The most used methods are render() and componentDidUpdate(). We should be familiar with what we are doing and what we need.
Unmounting
During this phase, component is removed from DOM.
This phase has only 1 method,
componentWillUnmount()
This method is called just before component is unmounted or destroyed. In this method setState() method should never be used, the reason is this method is never re-rendered as component instance. Once unmounted it can never be mounted again.
Syntax - componentWillUnmount()
This method is used for canceling network requests or removing event handlers, invalidating timers or cleaning any subscriptions created using componentDidMount().
Error Handling
During this phase, if there is any error found during rendering in lifecycle method or in the constructor or any other child component, there are 2 methods.
static getDerivedStateFromError()
This method is called when an error is generated by child component. It accepts an error thrown as a parameter and should return value to update state. This method is used during server-side rendering . It is called before commit phase; i.e., the DOM has not yet updated.
Syntax - static getDerivedStateFromError(error)
This method has direct access to state. In case of error, state is directly updated.
componentDidCatch()
This method is called after an error is thrown by child component. This method is called during commit phase; i.e., the DOM has been updated. That’s why side effects can be used in it. This method is called in the browser.
Syntax - componentDidCatch(error,info)
Error parameter returns an error that was thrown, while info parameter returns an object with a componentStack key. This method is used to log errors.
Summary
In this article we have reviewed component lifecycle in React and how it is used and executed. In the next article we will learn about fragments and pure components in ReactJs.