React Components: Functional vs Class-based

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 with this.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

FeatureClass-based ComponentsFunctional Components
SyntaxMore verbose, requires ES6 class syntaxSimpler, function-based syntax
State Managementthis.state and this.setState()useState Hook
Lifecycle MethodsAvailable via methods like componentDidMountManaged via useEffect Hook
PerformanceSlightly slower due to overhead of class methodsFaster due to simpler structure
UsageMostly legacy code nowPreferred in modern React development
Code ReadabilityCan be more complex and harder to followMore 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 of 0.
  • count is the state variable, and setCount 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, like componentDidMount in class components.

Why Functional Components Are Preferred

  1. Simplicity: Functional components are easier to write and understand, especially when dealing with smaller or simpler UI elements.
  2. Hooks: With Hooks, functional components can now manage state, context, and side effects, which was previously only possible with class components.
  3. Better Performance: Functional components are typically faster because they have less overhead compared to class components, which require more boilerplate code.
  4. 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.