Skip to main content

Lifecycle Methods

Lifecycle methods are special functions within React components that allow you to hook into specific points during a component's lifecycle. These methods provide opportunities to perform side effects, data fetching, subscriptions, and other actions essential for managing a component's behavior.

However, the approach to lifecycle methods differs between functional components using Hooks (introduced in React 16.8) and traditional class-based components. Here's a breakdown of both approaches:

Lifecycle Methods in Class-Based Components

Class components have access to a well-defined set of lifecycle methods:

  • constructor: Invoked once before the component is mounted (inserted into the DOM). Often used to initialize state using this.state = { ... }.
  • componentDidMount: Invoked immediately after a component is mounted. A common place to fetch data from APIs or perform other side effects.
  • componentDidUpdate: Invoked immediately after updating a component (when its state or props change). Useful for side effects based on state or prop changes.
  • componentWillUnmount: Invoked immediately before a component is unmounted (removed from the DOM). Ideal for cleaning up resources like subscriptions or timers.

Example:

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

componentDidMount() {
// Fetch data from an API (side effect)
}

handleClick = () => {
this.setState({ count: this.state.count + 1 });
};

render() {
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={this.handleClick}>Increment</button>
</div>
);
}
}

Lifecycle Methods with Hooks in Functional Components

While class components have built-in lifecycle methods, functional components achieve similar functionality using Hooks:

  • useState: Manages state within functional components.
  • useEffect: A versatile Hook for performing side effects, data fetching, subscriptions, and other actions that may affect component state. It can mimic various class-based lifecycle methods depending on the configuration.

Example (mimicking componentDidMount):

import { useState, useEffect } from 'react';

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

useEffect(() => {
// Fetch data from an API (side effect) on component mount
}, []); // Empty dependency array ensures effect runs only once on mount

const handleClick = () => {
setCount(count + 1);
};

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

Example (mimicking componentDidUpdate):

import { useState, useEffect } from 'react';

function UserList() {
const [users, setUsers] = useState([]);

useEffect(() => {
// Fetch data from an API (side effect) on component mount
fetch('https://api.example.com/users')
.then(response => response.json())
.then(data => setUsers(data));
}, []); // Empty dependency array for initial fetch

useEffect(() => {
// Update UI or perform actions based on changes to users state
console.log('Users updated:', users);
}, [users]); // Dependency array ensures effect runs on users state change

return (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}

In these examples, useEffect is configured to simulate the behavior of componentDidMount (empty dependency array) and componentDidUpdate (dependency array including the state variable users).

Choosing Between Hooks and Class-Based Lifecycle Methods

Class based lifecycle methods are more like lagacy code. They are often used in React applications that are older than Hooks. nowadays, it's recommended to use Hooks for all new projects.