React Component Lifecycle for Class & Functional
React Component Lifecycle: Class Components vs Functional Components
Understanding the React component lifecycle helps developers effectively manage, optimize, and debug applications. This guide covers both class components and functional components with hooks in standard React applications, detailing each lifecycle phase from mounting to unmounting, with full code examples, usage details, and outbound links. In addition, we include transitions to improve readability and clarity.
1. Mounting Phase
The mounting phase occurs when a component is created and inserted into the DOM for the first time. Therefore, this is the phase where initial setup should be performed.
Class Components – Mounting Methods
constructor(props)
- This method is invoked when the component is instantiated.
- It is typically used to initialize
this.state
and bind class methods. - However, side effects should be avoided at this stage.
static getDerivedStateFromProps(props, state)
- This static method runs before every render.
- Use it to update state based on changes to props.
- It must return an object to update the state or
null
if no update is needed.
render()
- This required method returns the JSX UI.
- It must be a pure function without side effects.
componentDidMount()
- Once the component has been inserted into the DOM, this method is called.
- It is ideal for running side effects such as API calls, setting up subscriptions, or modifying the DOM.
Example:
class UserCard extends React.Component {
constructor(props) {
super(props);
this.state = { userData: null };
console.log('Constructor');
}
static getDerivedStateFromProps(props, state) {
console.log('getDerivedStateFromProps');
return null;
}
render() {
console.log('Render');
return this.state.userData ? <div>Welcome, {this.state.userData.name}!</div> : <div>Loading...</div>;
}
componentDidMount() {
console.log('componentDidMount');
fetch(`/api/user/${this.props.userId}`)
.then(res => res.json())
.then(data => this.setState({ userData: data }));
}
}
Functional Components – Mounting with Hooks
In functional components, hooks are used instead of lifecycle methods.
useState()
is used to initialize state.useEffect(() => { ... }, [])
mimics the behavior ofcomponentDidMount()
.
Example:
import React, { useEffect, useState } from 'react';
function UserCard({ userId }) {
const [userData, setUserData] = useState(null);
useEffect(() => {
console.log('useEffect [] – mounted');
fetch(`/api/user/${userId}`)
.then(res => res.json())
.then(data => setUserData(data));
}, []);
return userData ? <div>Welcome, {userData.name}!</div> : <div>Loading...</div>;
}
2. Updating Phase
This phase is triggered when props or state change, which causes a re-render.
Class Components – Updating Methods
static getDerivedStateFromProps()
- It continues to run before every render.
shouldComponentUpdate(nextProps, nextState)
- This method determines whether the component should proceed with re-rendering.
- Return
false
to skip rendering, which can improve performance.
render()
- Renders the updated UI using new props and/or state.
getSnapshotBeforeUpdate(prevProps, prevState)
- This method is called before the DOM is updated.
- It can be used to capture information from the DOM, such as scroll position.
componentDidUpdate(prevProps, prevState, snapshot)
- Called after the DOM has been updated.
- Use it to perform operations like API calls or additional DOM updates based on new props or state.
Example:
componentDidUpdate(prevProps, prevState) {
if (prevProps.userId !== this.props.userId) {
console.log('Props changed, fetch new user');
fetch(`/api/user/${this.props.userId}`)
.then(res => res.json())
.then(data => this.setState({ userData: data }));
}
}
Functional Components – Updating with Hooks
To handle updates, use useEffect
with a dependency array:
- The effect only runs when the specified values change.
Example:
useEffect(() => {
let isCurrent = true;
fetch(`/api/user/${userId}`)
.then(res => res.json())
.then(data => isCurrent && setUserData(data));
return () => {
isCurrent = false; // cleanup before next run
};
}, [userId]);
3. Unmounting Phase
This final phase occurs when a component is removed from the DOM. It is crucial to clean up to prevent memory leaks.
Class Components
componentWillUnmount()
- Use this method to perform any necessary cleanup.
- For example, clear intervals or remove event listeners.
Example:
componentWillUnmount() {
clearInterval(this.timer);
console.log('Component unmounted');
}
Functional Components – Cleanup with Hooks
The cleanup function can be returned from useEffect
.
Example:
useEffect(() => {
const intervalId = setInterval(() => console.log('Tick'), 1000);
return () => {
clearInterval(intervalId);
console.log('Cleanup on unmount');
};
}, []);
Lifecycle Diagrams & Resources
Summary
Phase | Class Component | Functional Component |
---|---|---|
Mounting | constructor, render, componentDidMount | useEffect(() => …, []) |
Updating | render, componentDidUpdate | useEffect(…, [deps]) |
Unmounting | componentWillUnmount | return cleanup in useEffect |
Best Practices:
- Keep
render()
pure by avoiding side effects. - Prefer functional components with hooks for modern development.
- Always return a cleanup function in
useEffect
when necessary. - Use
shouldComponentUpdate
orReact.memo
for optimization.
Next, try converting a class component into a functional one using hooks. Observe how each lifecycle phase translates and see the impact on maintainability.
By fully understanding the React lifecycle, you can write more predictable, maintainable, and high-performance applications.
Read more:
Basic issues when working on Frontend Web development
Share this content:
Post Comment