Sitemap
React Masters

React Masters

React Masters is one of the leading React JS training providers in Hyderabad. Industry experts with vast and varied knowledge give our React Js training.

What is React Lifecycle

6 min readMay 17, 2024

--

Introduction:

React, a popular JavaScript library developed by Facebook is widely used for building user interfaces, particularly single-page applications. A fundamental concept in React is the component lifecycle. Understanding the React lifecycle is crucial for optimizing performance, managing state, and handling side effects effectively.

What is the React Lifecycle?

The React lifecycle refers to the series of phases that a React component goes through from its creation to its destruction. Each phase provides specific lifecycle methods that allow developers to hook into and manage different stages of a component’s existence. The lifecycle can be broadly categorized into three main phases: Mounting, Updating, and Unmounting.

Press enter or click to view image in full size
Stages of lifecycle components in React

A) Mounting Phase

The mounting phase is the initial phase where a component is created and inserted into the DOM. This phase includes the following methods:

1. constructor()

The constructor() method is the first method called in the lifecycle. It is used to initialize the state and bind event handlers. It’s important to call super(props) within the constructor to access this.props.

Example:

class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
}

2. static getDerivedStateFromProps()

This method is invoked right before calling render(), both on the initial mount and on subsequent updates. It should return an object to update the state or null to update nothing.

Example:

static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.someValue !== prevState.someValue) {
return { someValue: nextProps.someValue };
}
return null;
}

3. render()

The render() method is the only required method in a class component. It returns the React elements that make up the component. This method should be pure, meaning it should not modify the component state.

Example:

render() {
return (
<div>{this.state.count}</div>
);
}

4. componentDidMount()

The componentDidMount() method is called immediately after the component is inserted into the DOM. It is typically used for making API calls, setting up subscriptions, or initiating any DOM-related operations.

Example:

componentDidMount() {
fetch('/api/data')
.then(response => response.json())
.then(data => this.setState({ data }));
}

B) Updating Phase

The updating phase occurs when a component’s state or props change. This phase includes the following methods:

1. static getDerivedStateFromProps()

As mentioned earlier, this method is called during both mounting and updating phases.

2. shouldComponentUpdate()

The shouldComponentUpdate() method is invoked before rendering when new props or state are being received. This method allows you to prevent unnecessary re-renders by returning false.

Example:

shouldComponentUpdate(nextProps, nextState) {
return nextState.count !== this.state.count;
}

3. render()

The render() method is called during the updating phase as well.

4. getSnapshotBeforeUpdate()

The getSnapshotBeforeUpdate() method is called right before the DOM is updated. It allows you to capture some information from the DOM (e.g., scroll position) before it changes.

Example:

getSnapshotBeforeUpdate(prevProps, prevState) {
if (prevState.count !== this.state.count) {
return document.getElementById('myDiv').scrollHeight;
}
return null;
}

5. componentDidUpdate()

The componentDidUpdate() method is called immediately after the component's updates are flushed to the DOM. This method can be used to perform DOM operations or network requests based on the previous state or props.

Example:

componentDidUpdate(prevProps, prevState, snapshot) {
if (snapshot !== null) {
const myDiv = document.getElementById('myDiv');
myDiv.scrollTop = myDiv.scrollHeight - snapshot;
}
}

C) Unmounting Phase

The unmounting phase is the final phase of a component’s lifecycle, where it is removed from the DOM. This phase includes the following method:

1. componentWillUnmount()

The componentWillUnmount() method is called immediately before a component is destroyed. This method is used to perform cleanup operations such as invalidating timers, canceling network requests, or cleaning up subscriptions.

Get React Masters’s stories in your inbox

Join Medium for free to get updates from this writer.

Example:

componentWillUnmount() {
clearInterval(this.timerID);
}

Additional Lifecycle Methods

1. componentDidCatch()

The componentDidCatch() method is used for error handling in React components. It catches errors in any component below it in the tree and logs them. It also allows you to display a fallback UI.

Example:

componentDidCatch(error, info) {
logErrorToService(error, info);
}

2. shouldComponentUpdate()

While already mentioned in the updating phase, it’s worth noting that this method plays a crucial role in performance optimization by controlling the re-rendering process.

Functional Components and Hooks

With the introduction of React Hooks, functional components can also manage state and lifecycle events. The most common hooks related to lifecycle management are:

1. useState

useState is used to add state to a functional component.

Example:

const [count, setCount] = useState(0);

2. useEffect

useEffect is used to perform side effects in functional components. It combines the capabilities of componentDidMount(), componentDidUpdate(), and componentWillUnmount().

Example:

useEffect(() => {
document.title = `You clicked ${count} times`;
return () => {
// Cleanup if needed
};
}, [count]);

lifecycle hooks in react functional component

In React, functional components have become more prevalent due to their simplicity and the introduction of hooks in React 16.8. Lifecycle hooks, which were traditionally available only in class components, can now be used in functional components through these hooks. Understanding how to use these hooks effectively is crucial for managing state and side effects in your applications.

1. useState Hook

The useState hook is used to add state to functional components. It returns an array with two elements: the current state and a function to update it.

import React, { useState } from 'react';

function Counter() {
const [count, setCount] = useState(0);

return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}

2. useEffect Hook

The useEffect hook is used to handle side effects in functional components, such as fetching data, directly interacting with the DOM, and setting up subscriptions or timers. It serves a similar purpose to the lifecycle methods componentDidMount, componentDidUpdate, and componentWillUnmount in class components.

Basic usage:

import React, { useState, useEffect } from 'react';

function DataFetcher() {
const [data, setData] = useState(null);

useEffect(() => {
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => setData(data));
}, []); // Empty array means this effect runs once, like componentDidMount

return (
<div>
{data ? <p>Data: {data}</p> : <p>Loading...</p>}
</div>
);
}

Effect Cleanup:

Sometimes, you need to clean up side effects to avoid memory leaks, which is particularly important for effects like subscriptions and timers.

import React, { useState, useEffect } from 'react';

function Timer() {
const [count, setCount] = useState(0);

useEffect(() => {
const interval = setInterval(() => {
setCount(prevCount => prevCount + 1);
}, 1000);

// Cleanup function
return () => clearInterval(interval);
}, []); // Empty array means this effect runs once

return (
<div>Count: {count}</div>
);
}

3. useContext Hook

The useContext hook allows functional components to subscribe to React context without introducing nested consumers.

import React, { useContext } from 'react';

const ThemeContext = React.createContext('light');

function ThemedButton() {
const theme = useContext(ThemeContext);

return (
<button style={{ background: theme === 'dark' ? '#333' : '#CCC' }}>
I am styled by theme context!
</button>
);
}

4. useReducer Hook

The useReducer hook is useful for managing complex state logic that involves multiple sub-values, similar to how Redux works.

import React, { useReducer } from 'react';

const initialState = { count: 0 };

function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
throw new Error();
}
}

function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);

return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
</div>
);
}

5. useMemo and useCallback Hooks

These hooks help optimize performance by memoizing values and functions to prevent unnecessary re-renders.

useMemo:

import React, { useState, useMemo } from 'react';

function ExpensiveComputationComponent({ number }) {
const [count, setCount] = useState(0);

const computedValue = useMemo(() => {
return expensiveComputation(number);
}, [number]); // Only re-compute when number changes

return (
<div>
<p>Computed Value: {computedValue}</p>
<button onClick={() => setCount(count + 1)}>Re-render</button>
</div>
);
}

function expensiveComputation(num) {
// Simulate expensive computation
return num * 2;
}

useCallback:

import React, { useState, useCallback } from 'react';

function ParentComponent() {
const [count, setCount] = useState(0);

const handleClick = useCallback(() => {
setCount(prevCount => prevCount + 1);
}, []); // Function stays the same across renders

return (
<div>
<p>Count: {count}</p>
<ChildComponent onClick={handleClick} />
</div>
);
}

function ChildComponent({ onClick }) {
return <button onClick={onClick}>Increment</button>;
}

React’s functional components combined with hooks provide a powerful and flexible way to handle state and lifecycle events. By mastering these hooks, you can write more concise and readable code, leveraging the full potential of React’s modern capabilities.

Conclusion

Understanding the React lifecycle is fundamental for building efficient and effective React applications. By mastering lifecycle methods and hooks, you can optimize your components, manage state effectively, and handle side effects with ease. Whether you’re working with class components or functional components, a deep knowledge of the lifecycle will significantly enhance your development skills and lead to better-performing applications.

--

--

Written by React Masters

React Masters is one of the leading React JS training providers in Hyderabad. Industry experts with vast and varied knowledge give our React Js training.