React comes with many lifecycle methods. Each of them has their own purpose and acts during different phases of a component’s lifetime, like mounting, updating, unmounting, or during error handling.
Let’s take a look at them one by one:
This includesconstructor()
static getDerivedStateFromProps()
render()
andComponentDidMount()
These all are called when a component is made and inserted into a DOM. Among them, static getDerivedStateFromProps()
isn’t used much. We’ll examine the others closely.
If you are a React Hooks fan then you can use the useEffect hook with an empty array as the second argument to use it only during the mounting phase.
Next within the list, we’ve got updates. As the name suggests, they are called when an update event occurs, like a change of props or state.
These methods includestatic getDrivedStateFromProps()
shouldComponentUpdate()
render()
getSnapshotBeforeUpdate()
componentDidUpdate()
Among them, only the render()
and componentDidUpdate()
methods are truly used. We’ll have a good look at them.
For React Hook users, you can use the useEffect hook with the second argument as the state or prop value, which when updated will call the hook again.
Now it’s time to see what methods are called when a component gets removed from DOM.
The only method we have in this iscomponentWillUnmount().
For React Hook users, we can again use the useEffect hook with a return function or value to use during the unmounting phase.
This includes methods which are called when errors occur anywhere. These are not used most of the time, so we will not discuss them much. These methods includeStatic getDrivedStateFromError()
componentDidCatch()
For React Hook users, we can make state hasError, which will initially be false, then we can set it true using setHasError in the catch block if we are using try-catch to handle the error. Or, we can simply use setHasError to set hasError to true where the error can occur.
Take a look at the following figure to see their order.
Or you can refer to this simple version.
If you have ever used object-oriented programming then you should be familiar with constructors. Constructors are the first ones to be called, even before a component is mounted. So we can use them to initialize state and bind methods. In React we have to call super(props) in constructors so that we can use this.props or else it will be empty. Also, we should not call setState()
in it.
Example
1
2
3
4
5
6
7
8
constructor(props) {
super(props);
// Don't call this.setState() here!
this.state = {
page: 0
};
this.handleClick = this.handleClick.bind(this);
}
In the above example, we have initialized the state and bind handleClick functions.
This is the function from which a DOM will receive the react element, variables like string, number, booleans or null, arrays, and fragments. This should not modify anything. Such a function in React terms is known as a pure function. This function makes use of this.props and this.state. This is the only required method among all of them. For interacting with the browser we use componentDidMount()
.
Example
1 2 3 4 5 6 7 8 9 10 11
render() { const applycolor = { 'color': 'white' } return ( <div style={applycolor}> <h1>Hello</h1> <p>Current state is {this.state.curr}</p> </div> ); }
In this example, I have defined an applycolor object which is passed to style prop of <div>
to provide styling to div. I have also used this.state.x to display the value of state ‘curr’. You can see that we are using {} inside the return statement, this is how JSX works. If you are not familiar with JSX you should look at the JSX documentation.
render()
method is also called during the updating phase since we may need to re-render some components when some props or states change. For example, if we are rendering time we need to re-render time after every second/minute based on what we are showing.
Now let’s make some changes to our states. This method is called immediately after a component is mounted. This is the place where we do initialization. We can use setState()
in this method.
You may have been confused about why we have constructors and also need the componentDidMount()
method. It is true that we can use the constructor for initialization but there is a time when we need to measure some DOM node before rendering something that depends on its position, size, or other parameters. For example, modals during such situations need componentDidMount()
.
Example
1
2
3
4
5
6
7
8
9
componentDidMount() {
// Data fetch() calls
fetch('https://something.com/posts')
.then(response => response.json()) //response
.then(result => this.setState({
posts: result
})) //set state
.catch(e => console.error(e)); //error catch
}
In the above example, I have shown a case where we need componentDidMount()
in place of the constructor. We are fetching data and assigning the posts with response data. But more accurately we should use the async-await functionality of Javascript.
We can use the useEffect hook as componentDidMount simply bypassing the second argument, which in this case will be an empty array.
Example
1
2
3
4
5
6
7
8
9
const example = () {
// useEffect as componentDidMount
useEffect(() => {
console.log('called component gets mounted on DOM')
}, []);
return (
<h1>render on DOM</h1>
);
}
In the example above we have passed the empty array as the second argument. This tells React that we only need useEffect to be called when that component mounts.
As the name suggests, this method is called immediately after updating takes place. We can perform some operations which we want to get executed every time some props or state updates. We can also use setState()
in this method, but it should be inside some condition or else it may result in an infinite loop.
Example
1 2 3 4 5 6
componentDidUpdate(prevProps) { // Typical usage (don't forget to compare props): if (this.props.post !== prevProps.post) { this.fetchData(this.props.post); } }
In the above example, we are comparing props before doing our work (here, data fetching). This is to avoid the infinite loop.
We can use the useEffect hook as componentDidUpdate bypassing state or props value (which on update calls useEffect) as the second argument.
Example
1
2
3
4
5
6
7
8
9
10
11
const example = ({
prevProps
}) {
// useEffect as componentDidUpdate
useEffect(() => {
console.log('called every time prop get updated')
}, [prevProps]);
return (
<h1>render on DOM</h1>
);
}
In the example above we have passed prevProps within an array as the second argument, this tells React that we want this useEffect to be called every time prevProps get updated. If we want it to be called for an update of multiple props or states then we can pass multiple props or states in an array as the second argument or we can use multiple useEffect if needed.
Now for our last method, we have componentWillUnmount()
which is called before a component is unmounted and deleted. We can perform some clean-up in this method, like unsubscriptions. Since this is called when the component unmounts, we can not use setState()
since the component will not re-render after this.
Example
1 2 3 4
componentWillUnmount() { console.log('componentWillUnmount call') alert('Post has been deleted'); }
In the above example, we are simply printing a message in the console and using alert()
to show an alert to the user. This will get printed after all other lifecycle methods.
We can use the useEffect hook as componentWillUnmount by returning a value or a function from the useEffect hook.
Example
1
2
3
4
5
6
7
8
9
10
11
const example = () {
// useEffect as componentWillUnmount
useEffect(() => {
return () => {
console.log('called when component unmount');
}
}, []);
return (
<h1>render on DOM</h1>
);
}
In the example above we are returning a function from useEffect which will be called when the component unmounts.
Now we have covered all important lifecycle methods. But if you want to learn about others then I recommend you to have a look at the React documentation for reference.
React follows a proper path of calling all lifecycle methods, which are called in different phases of a component’s lifetime. Starting from before the component is created, then when the component is mounted, updated, or unmounted, and finally during error handling.
All of them have their own roles but some are used more often than others. The only required method in the whole lifecycle is the render()
method. We can say that those lifecycle methods are the ones that provide React with its real power.