Component lifecycle methods are a series of events that happen at different stages of a component's existence, from its creation to its destruction. Understanding these lifecycle methods is crucial for managing state, side effects, and rendering in a React application. Here is an overview of the React component lifecycle for both class components and functional components using hooks:
It is the birth phase of the lifecycle of a ReactJS component. Here, the component starts its journey on a way to the DOM. In this phase, a component contains the default Props and initial State. These default properties are done in the constructor of a component. The initial phase only occurs once and consists of the following methods.
getDefaultProps()
It is used to specify the default value of this.props. It is invoked before the creation of the component or any props from the parent is passed into it. It used in older versions of React (before React 16).
class MyComponent extends React.Component {
render() {
return (
<div>{this.props.someProp}</div>
);
}
}
MyComponent.defaultProps = {
someProp: 'default value'
};
import React, { Component } from 'react';
class MyComponent extends Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
render() {
return (
<div>{this.state.count}</div>
);
}
}
export default MyComponent;
constructor(props) {
super(props);
this.state = {
count: 0,
};
}
This phase occurs when the component is being inserted into the DOM.
static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.someValue !== prevState.someValue) {
return { someValue: nextProps.someValue };
}
return null;
}
componentDidMount() {
fetch('/api/data')
.then(response => response.json())
.then(data => this.setState({ data }));
}
1. Called before re-rendering when new props or state are received.
2. Used to let React know if a re-render is necessary. Returns true or false.
shouldComponentUpdate(nextProps, nextState) {
return nextProps.someValue !== this.props.someValue;
}
render() {
return <div>{this.state.someValue}</div>;
}
getSnapshotBeforeUpdate(prevProps, prevState) {
if (prevProps.list.length < this.props.list.length) {
const list = this.listRef.current;
return list.scrollHeight - list.scrollTop;
}
return null;
}
1. Called immediately after the component updates.
2. Used for working with the DOM after changes and making network requests based on the old props or state.
componentDidUpdate(prevProps, prevState, snapshot) {
if (snapshot !== null) {
const list = this.listRef.current;
list.scrollTop = list.scrollHeight - snapshot;
}
}
componentWillUnmount() {
clearInterval(this.timerID);
}
static getDerivedStateFromError()
1. Called when a descendant component throws an error.
2. Used to update state to display an error message.
componentDidCatch()
1. Called after an error has been thrown by a descendant component.
2. Used for logging error information.
Timer Component with Lifecycle Methods:
import React, { Component } from 'react';
class Timer extends Component {
constructor(props) {
super(props);
this.state = {
time: props.start,
running: true,
};
this.timerID = null;
}
// Static method to update state based on props changes
static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.start !== prevState.time && prevState.running === false) {
return { time: nextProps.start };
}
return null;
}
// Start the timer when the component mounts
componentDidMount() {
this.startTimer();
}
// Decide whether the component should re-render
shouldComponentUpdate(nextProps, nextState) {
// Only update if time or running state changes
return nextState.time !== this.state.time || nextState.running !== this.state.running;
}
// Capture some information from the DOM before updates are made
getSnapshotBeforeUpdate(prevProps, prevState) {
if (prevState.time !== this.state.time) {
return { prevTime: prevState.time };
}
return null;
}
// Use the snapshot value to perform some action after the update
componentDidUpdate(prevProps, prevState, snapshot) {
if (snapshot !== null) {
console.log(`Time updated from ${snapshot.prevTime} to ${this.state.time}`);
}
}
// Clean up when the component unmounts
componentWillUnmount() {
this.stopTimer();
}
// Start the timer
startTimer = () => {
this.timerID = setInterval(() => {
this.setState((prevState) => ({ time: prevState.time + 1 }));
}, 1000);
};
// Stop the timer
stopTimer = () => {
clearInterval(this.timerID);
this.setState({ running: false });
};
render() {
return (
<div>
<h1>Timer: {this.state.time}</h1>
{this.state.running ? (
<button onClick={this.stopTimer}>Stop</button>
) : (
<button onClick={this.startTimer}>Start</button>
)}
</div>
);
}
}
export default Timer;