Understanding Functional Components vs. Class Components in React
Time to read: 5 minutes
In the world of React, there are two ways of writing a React component. One uses a function and the other uses a class. Recently functional components are becoming more and more popular, so why is that?
This article will help you understand the differences between functional and class components by walking through each one with sample code so that you can dive into the world of modern React!
Rendering JSX
First of all, the clear difference is the syntax. Just like in their names, a functional component is just a plain JavaScript function that returns JSX. A class component is a JavaScript class that extends React.Component
which has a render method. A bit confusing? Let’s take a look into a simple example.
As you can see, a functional component is a function that returns JSX. If you are not familiar with arrow functions introduced in ES6, you can also check out the example below without.
See render with functional component in CodePen
On the other hand, when defining a class component, you have to make a class that extends React.Component
. The JSX to render will be returned inside the render method.
Below is the same example but without using destructuring. If you are not familiar with destructuring, you can learn more about destructuring and arrow functions introduced in ES6!
See render with class component in CodePen
Passing props
Passing props can be confusing, but let’s see how they are written in both class and functional components. Let’s say we are passing props of the name “Shiori” like below.
Inside a functional component, we are passing props as an argument of the function. Note that we are using destructuring here. Alternatively, we can write it without as well.
In this case, you have to use props.name
instead of name.
Since it is a class, you need to use this
to refer to props. And of course, we can use destructuring to get name
inside props while utilizing class-based components.
See props with class component in CodePen
Handling state
Now we all know that we cannot avoid dealing with state variables in a React project. Handling state was only doable in a class component until recently, but from React 16.8, React Hook useState was introduced to allow developers to write stateful functional components. You can learn more about Hooks from the official documentation. Here we are going to make a simple counter that starts from 0, and one click on button will increment the count by 1.
Handling state in functional components
To use state variables in a functional component, we need to use useState
Hook, which takes an argument of initial state. In this case we start with 0 clicks so the initial state of count will be 0.
Of course you can have more variety of initial state including null
, string
, or even object
- any type that JavaScript allows! And on the left side, as useState
returns the current state and a function that updates it, we are destructuring the array like this. If you are a bit confused about the two elements of the array, you can consider them as a state and its setter. In this example we named them count
and setCount
to make it easy to understand the connection between the two.
See state with functional component in CodePen
Handling state in class components
The idea is still the same but a class component handles state a bit differently. Firstly, we need to understand the importance of the React.Component
constructor. Here is the definition from the official documentation:
“The constructor for a React component is called before it is mounted. When implementing the constructor for a React.Component subclass, you should call super(props) before any other statement. Otherwise, this.props will be undefined in the constructor, which can lead to bugs.”
Basically, without implementing the constructor and calling super(props), all the state variables that you are trying to use will be undefined. So let’s define the constructor first. Inside the constructor, you will make a state object with a state key and initial value. And inside JSX, we use this.state.count
to access the value of the state key we defined in the constructor to display the count. Setter is pretty much the same, just different syntax.
Alternatively, you can write an onClick
function. Remember, the setState
function takes argument(s) of state, props(optional) if needed.
See state with class component in Codepen
Lifecycle Methods
Finally, let’s talk about lifecycles. Hang on, we are almost there! As you already know, lifecycles play an important role in the timing of rendering. For those of you who are migrating from class components to functional components, you must be wondering what could replace lifecycle methods such as componentDidMount()
in a class component. And yes, there is a hook that works perfectly for the purpose, let’s check it out!
On Mounting (componentDidMount)
The lifecycle method componentDidMount
is called right after the first render completes. There used to be a componentWillMount
that happens before the first render, but it is considered legacy and not recommended to use in newer versions of React.
Replacing componentDidMount
, We use the useEffect
hook with the second argument of []
. The second argument of the useState
hook is normally an array of a state(s) that changes, and useEffect
will be only called on these selected changes. But when it’s an empty array like this example, it will be called once on mounting. This is a perfect replacement for a componentDidMount
.
Basically the same thing happens here: componentDidMount
is a lifecycle method that is called once after the first render.
On Unmounting (componentWillUnmount)
I am happy to tell you that we can also use a useState
hook for unmounting as well. But be careful, the syntax is a bit different. What you need to do is return a function that runs on unmounting inside the useEffect
function. This is especially useful when you have to clean up the subscriptions such as a clearInterval
function, otherwise it can cause a severe memory leak on a bigger project. One advantage of using useEffect
is that we can write functions for both mounting and unmounting in the same place.
See lifecycle with functional component in Codepen
See life cycle with class component in Codepen
In conclusion, which is better: functional or class components?
There are pros and cons in both styles but I would like to conclude that functional components are taking over modern React in the foreseeable future.
As we noticed in the examples, a functional component is written shorter and simpler, which makes it easier to develop, understand, and test. Class components can also be confusing with so many uses of this
. Using functional components can easily avoid this kind of mess and keep everything clean.
It should also be noted that the React team is supporting more React hooks for functional components that replace or even improve upon class components. To follow up, the React team mentioned in earlier days that they will make performance optimizations in functional components by avoiding unnecessary checks and memory allocations. And as promising as it sounds, new hooks are recently introduced for functional components such as useState
or useEffect
while also promising that they are not going to obsolete class components. The team is seeking to gradually adopt functional components with hooks in newer cases, which means that there is no need to switch over the existing projects that utilize class components to the entire rewrite with functional components so that they can remain consistent.
Again, there are a lot of valid coding styles in React. Yet I prefer using functional components over class components for those reasons listed above. I hope this article helped you get more familiar with modern React. To learn more, check out the official documentation! You can also check out this guide on React for frontend developers or our post on building a Twilio Video app see a practical use of functional components with hooks.
Shiori Yamazaki is a Software Engineering Intern on the Platform Experience team. She loves to develop modern web applications. She can be reached at syamazaki [at] twilio.com or LinkedIn.
Check out these related posts:
Related Posts
Related Resources
Twilio Docs
From APIs to SDKs to sample apps
API reference documentation, SDKs, helper libraries, quickstarts, and tutorials for your language and platform.
Resource Center
The latest ebooks, industry reports, and webinars
Learn from customer engagement experts to improve your own communication.
Ahoy
Twilio's developer community hub
Best practices, code samples, and inspiration to build communications and digital engagement experiences.