How React Hooks Made Class Components A Thing Of The Past
...and why Functional Components will continue to shine
Learning React certainly does not come without it's challenges. The concepts of components, props, and state can be a bit tricky to comprehend, especially as a new developer. Fortunately throughout my introductory period to React, I had the benefit of living within close proximity of an uncle, who has nearly 40 years of software engineering experience! Having spent most of his career as a backend Java developer, I knew that he himself had recently been tasked with building out a React UI, so naturally I was eager to share with him my work.
Much to my surprise however, he seemed a bit perplexed by my code, instantly citing his unfamiliarity with the given syntax. Having only implemented functional components to this point in the early-stages of my React development career, his confusion served as my introduction to the opposition - class components.
Curious as to why I had been steered to learn one method as opposed to another, along with the possible disparities, and benefits of each, I decided to dig a little deeper in search of a better understanding. So let's start with the basics.
Basic Syntax
Here is what a functional React component looks like, using an ES6 arrow function:
import React from "react";
const FunctionalComponent = () => {
return <h1>Functional Component</h1>;
};
Pretty straight-forward, huh?
...and here is the equivalent syntax written as a React class component:
import React, { Component } from "react";
class ClassComponent extends Component {
render() {
return <h1>Class Component</h1>;
}
}
While minor, you may notice a few discrepancies from syntax to syntax. Most notably the declaration of class
in none other than (you guessed it!) - the class component. Additionally the class component also requires the use of the render()
method within.
Now these may not seem like very substantial differences, but will ultimately prove to be an early indication of the disparities between these two approaches. Before we dive too deep into their respective profiles however, I think it's important to provide some context to the history of React components.
The History of Components In React
While both functional and class components have existed since the early days of React back in 2013, class components became the preferred method of component declaration - and for good reason! Their ability to establish state, a core fundamental of the React library, along with the lifecycle management associated with that state, gave class components a serious leg-up when determining which component-type to implement. For the longest time functional components were merely reserved for very primitive, state-less components, that solely rendered JSX content (an HTML-like extension of the Javascript language, used to render content to the DOM).
Given these obvious limitations, functional components often took the backseat to their superior class-component counterparts. This all changed in 2019 however with the release of React v16.8, and the introduction of a concept called hooks. The inception of React hooks single-handedly catapulted functional components overnight.
React Hooks & The Emergence of Functional Components
Hooks, cleverly named for their ability to hook into React features, now allowed developers to access many key benefits of the React library within functional components, once designated strictly for class components. The ability to incorporate state, and manage component lifecycles, along with a slew of other capabilities, now gave functional components the spotlight.
If functional components were playing catch-up however, was it simply a matter of shiny object syndrome that now gave them the edge over their predecessor?
Not exactly. While hooks seemingly leveled the playing field, they also offered some additional benefits as well. The ability to create your own custom hooks gave developers the ultimate freedom to implement near-limitless functionality within their React applications. Not to mention some of the syntactical disparities foreshadowed above.
Syntax Revisited
Now that we have a pretty good understanding of some of the history, and differences between functional and class components in React, let's tie it all together and see how they interact with props and state.
Here is an example of a functional component accepting and utilizing a prop that was passed down from a parent component:
import React from "react";
const FunctionalComponent= ({animal}) => {
return (
<h1>My favorite animal is a {animal}!</h1>
)
}
export default FunctionalComponent;
On the contrary, here is a class component accepting the same prop:
import React, { Component } from "react";
class ClassComponent extends Component{
render(){
const {animal} = this.props
return <h1>My favorite animal is a {animal}!</h1>
};
};
export default ClassComponent;
Aside from the additional line of code, you'll notice the class component accepting the prop through the use of the this
keyword, a declaration unnecessary to functional components.
What about setting state though?
The following is an example of a functional component establishing state using the useState
React hook:
import React, {useState} from "react";
const Scoreboard= () => {
const [score, setScore] = useState(0);
return (
<div>
<p>Score: {score}</p>
<button onClick={() => setScore(score + 1)}>+</button>
</div>
);
};
export default Scoreboard;
State is established much differently in class components, again relying on the this
keyword:
import React, {Component} from "react";
class Scoreboard extends Component {
state = {
score: 0
};
render() {
return (
<div>
<p>Score: {this.state.score}</p>
<button onClick={() => this.setState({ score: this.state.score + 1 })}>
+
</button>
</div>
);
}
}
export default Scoreboard;
Now i'll let you be the judge, but even at the micro level, we are starting to notice some more dramatic differences. Functional components seem to accomplish the same tasks as class components, but in a much more efficient manner. Also imagine these disproportions as our components continue to scale! In terms of syntax, functional components carry a clear edge, as they offer cleaner and more readable code (depending on who you ask).
Conclusion
All good things must come to an end at some point, right? Well there should be little doubt by now why we have seen such an emergence of functional components over the past few years. Once considered the red-headed step-children of component declaration, have now become the standard method for writing React components, all thanks to version 16.8. The addition of hooks coupled by a more favorable syntax, have nearly made class components an urban legend.
Don't expect this standard to change anytime soon either. While the React team hasn't made a push to fully deprecate class components just yet, they have stated that they plan to continue allocating their efforts towards functional components - in a push to cover all existing use cases of classes, by way of hooks. In other words, it's safe to say that the future looks bright for functional components!
That being said, if you haven't already adopted a more modern React, your next project is a great opportunity to do so! There is certainly value in familiarizing yourself with both methods, given what you may come across in legacy code - but for now functional components shall reign supreme in the foreseeable future, and the obsolescence of class components is surely inevitable.