Class Components Vs. Functional Components in React

When I started my React journey back in 2019, hooks had just been introduced a couple of months earlier in February of that year. After coming across multiple sources vouching for the ease and simplicity of functional components compared to class-based components, I was sold. Right then and there, I decided functional components were the way to go and that I never needed to learn anything about class components. It wasn’t long before I realized that while I was ready to dive into hooks, not everyone was willing to transition so quickly.
At the time, I’d estimate that about 95% of the code snippets I found online (StackOverflow, YouTube tutorials, CodeSandbox, etc.) to help me learn React were written using class components. That presented a dilemma.
In the end, I decided it would be beneficial to learn both. And so I did.
What Are Class Components?
Before React v16.8, class components were the primary way React managed state in applications. State is defined as any piece of data capable of changing (via user actions or interactions), causing the UI to re-render with updated data.
In class components, state is typically initialized inside the constructor, as shown in the snippet below. The constructor() is a method that is automatically called when a class instance is created. Additionally, because we are extending the React class (React.Component), super() must be called. This invokes the constructor of the parent class and allows the subclass to function properly.
In short:
Use
constructor()when creating your own classes.When extending an existing class, always call
super()inside the constructor.
The this keyword refers to the current class instance. Inside the constructor, this refers to the component instance being created. Inside methods like handleNameChange and handleSubmit, this still refers to the component instance. Because arrow functions do not create their own this context, they safely allow access to component state using this.setState().
import React from "react";
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
tempName: "",
name: "Jane Doe",
};
}
handleNameChange = (e) => {
this.setState({ tempName: e.target.value });
};
handleSubmit = (e) => {
e.preventDefault();
this.setState({ name: this.state.tempName, tempName: "" });
};
render() {
return (
<div className="App">
<h1>Hello, {this.state.name}!</h1>
<h2>If you want to change your name, enter it below.</h2>
<input
type="text"
name="name"
value={this.state.tempName}
onChange={this.handleNameChange}
/>
<button type="submit" onClick={this.handleSubmit}>
Submit
</button>
</div>
);
}
}
What Are Functional Components?
Originally, functional components were used for simple, stateless presentational components because they lacked the ability to manage state like class components. With the release of React v16.8, Hooks were introduced, allowing functional components to manage state and side effects.
Hooks are functions that allow developers to use state and lifecycle features inside function components. A common convention is that Hooks start with the prefix use.
To convert the class component above into a stateful functional component, we can use the useState Hook. Similar to how the constructor holds state in class components, useState manages state inside functional components.
import React, { useState } from "react";
export default function App() {
const [name, setName] = useState("Jane Doe");
const [tempName, setTempName] = useState("");
const handleNameChange = (e) => {
setTempName(e.target.value);
};
const handleSubmit = (e) => {
e.preventDefault();
setName(tempName);
setTempName("");
};
return (
<div className="App">
<h1>Hello, {name}!</h1>
<h2>If you want to change your name, enter it below.</h2>
<input
type="text"
name="name"
value={tempName}
onChange={handleNameChange}
/>
<button type="submit" onClick={handleSubmit}>
Submit
</button>
</div>
);
}
In this article, I've used just one hook for simplicity. Check out the first article in the React Hooks series: React Hooks Pt. I - useState.
Numerous times, I found myself discouraged when I couldn’t complete certain projects because I struggled to understand how to convert class components into functional ones. So aside from the obvious syntax differences, what truly distinguishes these two component types?
In short: not much.
Functional components have always been a core part of React. However, before version 16.8, they could not manage state. Developers were required to use class components for state management. With the introduction of Hooks in React v16.8, functional components gained the ability to manage state and lifecycle behavior. This innovation removed the need to rely exclusively on class components.
Conclusion
Both functional and class components ultimately produce the same results. The choice between them largely depends on your project requirements and team preferences. That said, functional components with Hooks have become the modern standard due to their simplicity, readability, and flexibility.



