In React, components are the building blocks of your application. Initially, there were class-based components and functional components. However, with the introduction of Hooks in React 16.8, functional components became the recommended approach due to their simplicity and flexibility.
In this module, we will cover:
- The basics of class-based and functional components
- Key differences between them
- How to manage state and side effects
- Why functional components are now preferred
Class-based Components: The Traditional Approach
Class-based components were the original way to define components in React. They are ES6 classes that extend React.Component
and can have lifecycle methods, state, and more.
Here’s an example of a basic class component:
import React, { Component } from 'react';
class MyClassComponent extends Component {
constructor(props) {
super(props);
this.state = {
message: 'Hello from class component!',
};
}
render() {
return <h1>{this.state.message}</h1>;
}
}
export default MyClassComponent;
Key Features of Class-based Components:
- State is managed using the
this.state
object and updated withthis.setState()
. - Lifecycle methods (e.g.,
componentDidMount
,componentDidUpdate
,componentWillUnmount
) are used to perform actions during different phases of the component lifecycle. - More verbose and complex syntax due to class definitions and lifecycle methods.
Functional Components: The Modern Approach
Functional components, on the other hand, are simpler and typically involve just a function that returns JSX. They were initially stateless, but with the introduction of Hooks, functional components can now manage state, side effects, and perform other tasks previously possible only with class components.
Here’s an example of a functional component:
import React from 'react';
const MyFunctionalComponent = () => {
return <h1>Hello from functional component!</h1>;
};
export default MyFunctionalComponent;
Key Features of Functional Components:
- Simpler syntax without the need for classes or lifecycle methods.
- Initially stateless, but with Hooks, functional components can now manage state and side effects.
- More concise and easier to understand, especially for smaller components.
Differences Between Class-based and Functional Components
Feature | Class-based Components | Functional Components |
---|---|---|
Syntax | More verbose, requires ES6 class syntax | Simpler, function-based syntax |
State Management | this.state and this.setState() | useState Hook |
Lifecycle Methods | Available via methods like componentDidMount | Managed via useEffect Hook |
Performance | Slightly slower due to overhead of class methods | Faster due to simpler structure |
Usage | Mostly legacy code now | Preferred in modern React development |
Code Readability | Can be more complex and harder to follow | More readable and easier to maintain |
Managing State in Functional Components
In functional components, state is handled using the useState
hook.
Example with useState
:
import React, { useState } from 'react';
const Counter = () => {
const [count, setCount] = useState(0);
const increment = () => setCount(count + 1);
return (
<div>
<h1>{count}</h1>
<button onClick={increment}>Increment</button>
</div>
);
};
export default Counter;
useState(0)
initializes the state with a value of0
.count
is the state variable, andsetCount
is the function used to update it.
Managing Side Effects in Functional Components
In class-based components, side effects (like fetching data) are managed using lifecycle methods. In functional components, you can achieve the same behavior using the useEffect
hook.
Example with useEffect
:
import React, { useState, useEffect } from 'react';
const FetchData = () => {
const [data, setData] = useState([]);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/posts')
.then((response) => response.json())
.then((data) => setData(data));
}, []); // Empty dependency array means this runs once, similar to componentDidMount
return (
<div>
{data.map((post) => (
<div key={post.id}>{post.title}</div>
))}
</div>
);
};
export default FetchData;
useEffect
runs the code inside the callback function after the component renders.- The empty dependency array (
[]
) makes the effect run only once, likecomponentDidMount
in class components.
Why Functional Components Are Preferred
- Simplicity: Functional components are easier to write and understand, especially when dealing with smaller or simpler UI elements.
- Hooks: With Hooks, functional components can now manage state, context, and side effects, which was previously only possible with class components.
- Better Performance: Functional components are typically faster because they have less overhead compared to class components, which require more boilerplate code.
- Better Code Organization: With hooks, you can logically group related state and effects together in a single function, making it easier to reuse logic across components.
When to Use Class Components
While functional components are the preferred approach in modern React development, there are still cases where you might need class components:
- Working with legacy codebases that are built using class components.
- When integrating with external libraries or APIs that require class components.
- React Native uses class components in certain cases, though it has been shifting to functional components as well.
However, these cases are becoming increasingly rare as functional components with hooks are now the standard.
Summary
In this module, we’ve explored the key differences between class-based and functional components. Functional components are now the go-to method for building React apps due to their simplicity, better performance, and the power of Hooks.
In the next module, we’ll dive into React State and the useState Hook, where you will learn how to manage state in functional components, a core concept for building interactive applications.