What is a Class-Based Component (CBC)?
In React, a Class-Based Component (CBC) is a component defined using ES6 classes, inheriting from React.Component
. CBCs are the traditional way to create stateful components and manage component life cycles. Although functional components with hooks are more popular now, CBCs are still used in many existing React applications.
class MyComponent extends React.Component {
render() {
return <div>Hello, World!</div>;
}
}
How to Use Props in CBC
Props in a CBC are accessed using this.props
. Props are passed to the component from its parent and are used to render dynamic content.
class MyComponent extends React.Component {
render() {
return <div>Hello, {this.props.name}!</div>;
}
}
// Usage
<MyComponent name="Alice" />;
Creating States in CBC
In CBC, the state is a built-in object used to contain data or information about the component that can change over time. State is initialized in the constructor. jsx
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0,
};
}
render() {
return <div>Count: {this.state.count}</div>;
}
}
Why Can’t We Update State Variables Directly?
State should not be updated directly using this.state.variable = value
because React will not be aware of the change and will not re-render the component. Instead, the setState
method is used to update the state, which triggers a re-render.
// Incorrect
this.state.count = 1;
// Correct
this.setState({ count: 1 });
Life-Cycle Methods of CBC
Lifecycle methods in CBC are special methods that are automatically called at different stages of a component’s life.
constructor()
: Initializes the component.render()
: Renders the component to the DOM.componentDidMount()
: Called after the component is mounted.componentDidUpdate()
: Called after the component updates.componentWillUnmount()
: Called just before the component is unmounted.
Parent-Child CBC Lifecycle Methods
In CBC, parent and child components have their own lifecycle methods. When a parent component renders, its lifecycle methods are executed first, followed by the child’s lifecycle methods. When unmounting, the child’s componentWillUnmount
is called before the parent’s.
What is componentDidMount
?
This lifecycle method is invoked immediately after a component is mounted (inserted into the tree). It is typically used for performing side effects, like making API calls or setting up subscriptions.
class MyComponent extends React.Component {
componentDidMount() {
// Code to run after component is mounted
fetchData();
}
render() {
return <div>Data loaded</div>;
}
}
Why Do We Use componentDidMount
to Make API Calls?
The componentDidMount
is ideal for making API calls because it is guaranteed to run once the component has been rendered to the DOM. This ensures that any required DOM elements are present and ready for interaction.
Why Does the Order of Lifecycle Method Calls Change in the Case of a Class with Multiple Class Components?
The order of lifecycle method calls changes because each component (parent and child) follows its own lifecycle. When rendering, the parent’s lifecycle methods are executed first, then the child’s. On unmounting, the child’s lifecycle methods are executed before the parent’s.
React Lifecycle Method Diagram
A visual representation of React’s lifecycle methods. It shows the sequence of method calls during mounting, updating, and unmounting phases. React’s official documentation provides a detailed lifecycle diagram.
Why is DOM Updating Costly?
Manipulating the DOM is expensive in terms of performance because it triggers reflows and repaints, which are resource-intensive operations. Frequent updates to the DOM can lead to slow rendering and a poor user experience. React mitigates this by using the virtual DOM to batch and optimize updates.
What is componentDidUpdate()
?
This method is called after the component is re-rendered due to changes in props or state. It can be used for tasks that need to happen after the DOM has been updated, such as interacting with the DOM or making network requests.
class MyComponent extends React.Component {
componentDidUpdate(prevProps, prevState) {
if (prevState.count !== this.state.count) {
// Perform some operation
}
}
render() {
return <div>{this.state.count}</div>;
}
}
What is componentWillUnmount()
?
This method is called just before the component is unmounted and destroyed. It’s typically used for cleanup, such as clearing timers, canceling network requests, or unsubscribing from subscriptions.
class MyComponent extends React.Component {
componentWillUnmount() {
// Cleanup code here
clearInterval(this.timerID);
}
render() {
return <div>Component will unmount</div>;
}
}
CBC v/s FC
Class-Based Components (CBC) and Functional Components (FC) are fundamentally different in how they manage state, lifecycle, and reactivity. While FCs are now preferred due to simplicity and the introduction of hooks, CBCs have been a foundational part of React and are more complex in terms of lifecycle management. Comparing them directly may lead to misunderstandings about the strengths and weaknesses of each approach.
How to Use Dependency Array to Re-Render Component in CBC
In functional components, the dependency array in useEffect
controls when the effect runs. In CBC, the equivalent would be using componentDidUpdate
and checking if certain props or state have changed before performing an action.
componentDidUpdate(prevProps) {
if (prevProps.data !== this.props.data) {
// Perform some operation
}
}
Why There is a Dependency Array (Why is it an Array?)
The dependency array in useEffect
is an array because you may want to specify multiple dependencies that should trigger the effect. This allows for more granular control over when the effect runs, based on changes to one or more variables.
Using setInterval
with CBC & why we reset setInterval
In a CBC, setInterval
can be used to run a function repeatedly at a specified interval. However, if you don’t clear the interval using clearInterval
, it will continue to run even after the component is unmounted, which can lead to memory leaks.
componentDidMount() {
this.timerID = setInterval(() => this.tick(), 1000);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
Using setInterval
with useEffect
In functional components, you can use setInterval
inside useEffect
. The cleanup function returned by useEffect
can be used to clear the interval when the component unmounts.
useEffect(() => {
const timerID = setInterval(() => {
console.log("Tick");
}, 1000);
return () => clearInterval(timerID); // Cleanup on unmount
}, []);
Returning a Function from useEffect
The function returned from useEffect
is a cleanup function. It is executed when the component unmounts or before the effect runs again due to a dependency change.
useEffect(() => {
const timerID = setInterval(() => {
console.log("Tick");
}, 1000);
return () => clearInterval(timerID); // Cleanup
}, []);
Why We Can’t Use Async Callback in useEffect
This is because the useEffect hook expects its effect function to return either a cleanup function or nothing at all. This is due to the useEffect() hook’s callback function’s asynchronous execution and lack of blocking. Therefore, we must follow a specific pattern if we want to call an asynchronous function inside the useEffect() hook.
The special pattern is to create a new function that is declared inside the useEffect() hook and that contains the async function, and then we can call this new function inside the useEffect() hook. Here’s an example:
import React, { useEffect } from "react";
function App() {
useEffect(() => {
async function fetchData() {
const response = await fetch("https://example.com/data");
const data = await response.json();
console.log(data);
}
fetchData();
}, []);
return <div>Hello World</div>;
}