Functional vs Class Components in React - Everything you need to know

Functional vs Class Components in React - Everything you need to know

In this article, You'll see everything you need to know about the Why, How, and When of using functional components in React. You only need a basic understanding of React, although knowing ES6 would be definitely helpful.

In this article, You'll see everything you need to know about the Why, How, and When of using functional components in React. You only need a basic understanding of React, although knowing ES6 would be definitely helpful.

What if I told you there was a way to make your React code easier to reason about, easier to test, and achieve better performance? You’d be interested — right? Well, it turns out functional components are an easy way to achieve all of these things and more.

What are Functional Components?

There are two main types of components in React. Class Components and *Functional Components. *The difference is pretty obvious. Class components are ES6 classes and Functional Components are functions. The only constraint for a functional component is to accept props as an argument and return valid JSX.

Let’s take a peek:

function Hello(props){
   return <div>Hello {props.name}</div>
}

Boom, that’s a functional component.

The key thing that makes this type of component different from a class component is the lack of state and lifecycle methods. This is why functional components are also commonly referred to as stateless components.

Here’s the same component, but written in ES6:

const Hello = ({name}) => <div>Hello {name}</div>

If you’ve never seen ES6 before don’t panic. It might look a little weird, but it’s not actually that complicated. This article should get you up to speed pretty quickly. Or you can just take my word that these two code snippets do the exact same thing and keep going.

Here’s the same component, but written as a class component:

class Hello extends Component{
   render(){
      return <div>Hello {this.props.name}</div>
   }
}

This snippet is a contradiction to the most basic rule. If you ever have a class component with only a render method – you should always make it a functional component.

So now you know the key differences that make functional components different from class components. Feel free to play around in Code Pen. This example is simple, but you can experiment with adding logic outside of jsx as well as nesting components.

Why use Functional Components?

You might be wondering what all the fuss is about for a type of component that actually removes functionality. But it turns out constraints are often super valuable.

Let’s get into it. Here are the 6 key reasons to start using functional components:

Functional components are easy to reason about

One of the main benefits of functional components is that they make your code easier to read and understand. If you’re working on a project by yourself, you might not think this is a big deal. But trust me. The first time you take a 1-month hiatus from working on a project and come back trying to figure out what your past self was thinking, you’ll understand.

Functional Components are easier to read in large part because you already know all of the things they *can’t do, *such as have hidden inputs or modify a hidden state. Especially with the use of prop destructuring, it’s very clear what’s going in and coming out of a functional component.

It’s hard to fully understand this benefit until you start more readily using functional components. So I encourage you to dive in. I’ve definitely felt the benefits in my own work.

Functional components are easy to test

It’s easier to test functional components because you don’t have to worry about hidden state or side effects. For every input (props), functional components have exactly one output.

Given certain props, I can assert exactly what the HTML output will be. This means you don’t have to rely on any mocking, state manipulation, or crazy testing libraries. It’s pretty awesome.

Functional components can potentially have a better performance

Since functional components offer no state or lifecycle methods, you would think that this would allow the internals of React to avoid unnecessary overhead such as lifecycle events. Unfortunately, this is currently not the case.

In the words of release notes:

“In the future, we’ll also be able to make performance optimizations specific to these components by avoiding unnecessary checks and memory allocations”

But even without these optimizations, functional components result in less code and faster bundles. This article estimates the current speed up at ~6% with future improvements estimated at ~45%.

Functional components are easy to debug

Functional components depend only on the props they are given to produce an output which in turn makes debugging easier. There is no need to continuously log the state of the component to understand what is going on.

If you know the props being passed in, it’s easy to trace the path of your code and figure out what is taking place.

Functional components are more reusable

This one might be a bit controversial. But by removing function level state, we often make our components easier to use and more widely applicable. Let’s take a peek at two implementations of a custom checkbox.

Functional Checkbox:

const Checkbox = ({ checked, label, handleClick }) => (
   <div
      className={checked ? 'Checkbox-container checked' : 'Checkbox-container'}
      onClick={handleClick}
      role="button"
      tabIndex={0}
      data-label={label}
   >
      <p className="label" data-label={label}>{label</p>
   </div>
);

Making the checkbox a functional component forces us to strip the component down to its most primitive features, which has the side effect of making it more generally applicable. Think of it as a forced best practice.

The checkbox component does not have to choose what its default state should be or what it should do when clicked. Instead, this is delegated to the higher level component. Could you write a class component in the exact same way? Sure, but a functional component** forces **us to follow best practices which results in a cleaner, more reusable component.

PropTypes

For some reason, some people seem to think that you can’t use PropTypes with functional components. It’s simply not the case. Here’s how I would add PropTypes to the Checkbox component.

Checkbox.propTypes = {
   checked: PropTypes.bool,
   label: PropTypes.string.isRequired,
   handleClick: PropTypes.func.isRequired,
};

Checkbox.defaultProps = {
   checked: true,
};

Class Checkbox:

render(){
   return(
      <div
         className={checked ? 'Checkbox-container checked' : 'Checkbox-container'}
         onClick={handleClick}
         role="button"
         tabIndex={0}
         data-label={label}
      >
         <p className="label" data-label={label}>{label</p>
      </div>
   );
}

First, let’s look at the render method of the class-based component. It looks pretty similar, except that we have the “this” keyword everywhere, and the Checkbox is managing some of its own state. It’s a little more confusing, but overall not too bad.

class Checkbox extends Component{
   constructor(){
      super();
      this.state = {
         checked: false,
      };
      this.handleClick = this.handleClick.bind(this);
   }

   handleClick(){
      this.setState({
         checked: !this.state.checked,
      })
   }

Now let’s look at the rest of the component. All of this code did not exist in the functional component.

If you’re wondering what that weird “.bind” is in the constructor – it has to do with managing the pesky “this” (you can read all about it here). Another thing we don’t have to deal with when we write functional components. Are you sensing a pattern?

Without meaning to, this example also shows many of the other reasons functional components are often preferable to class components. 11 lines of code compared to a total of 30 for the class component. The functional code is clearly easier to understand, and don’t even get me started about trying to test this class component…

To be fair, this class component is poorly written because I wanted to make a point. But the fact that it is so easy to create such a poorly written class component should tell you something.

Despite the scarier code, this component is really doing the same thing, but managing most of its own state. Because of this, we now have to choose some sensible defaults and hope they work in the future. What if we don’t always want the checkbox to toggle state when checked? Or what if we want our checkbox to start in the checked state? We either have to rely on some hackery or write a totally new component. Not ideal.

*Functional components can reduce coupling *

One of the core concepts used to describe clean code is coupling. Coupling describes the degree of dependency between one entity to another. If our code has low coupling, it means that we can change one area of our code without impacting another. This, in turn, makes our code more maintainable.

Once again, the constraints put in place by functional components force us to extract most of the logic that might normally live inside a component to either a higher level component, a state management library such as Redux, or the new React Context API*. *Separating logic from presentation sounds a lot like low coupling to me :).

When NOT to use Functional Components

If functional components are a hammer, it’s important to remember that not every problem is a nail. Class components are included in React for a reason.

The general heuristic I use is to always start with a functional component. If you find out you need lifecycle methods or it makes sense to have a small piece component level state, it’s trivial to refactor to a class component. I find this style of writing components keeps me from getting lazy and forces me to use functional components to their full potential.

Companies on the cutting edge of React development like Facebook, Netflix, and Airbnb all readily use functional components. It seems pretty clear the upsides outweigh the negatives.

When should you NOT use functional components? When you have no other option.

Recap

  • A Functional component is a function that takes props and returns JSX
  • They do not have state or lifecycle methods.
  • Functional components are easier to read, debug, and test. They offer performance benefits, decreased coupling, and greater reusability.
  • They with a few downsides … but I think the benefits strongly outweigh these. Use them whenever you can.
  • Functional components are built into React. You can get started adding them (and refactoring unnecessary class components) to your existing projects right away!

reactjs javascript

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

The essential JavaScript concepts that you should understand

The essential JavaScript concepts that you should understand - For successful developing and to pass a work interview

What is ECMAScript and How is it Different From JavaScript?

Many times developers use JavaScript and ECMAScript synonymously for each other. Though they are very closely linked to each other, it does not mean they are the same thing.here is a complete story on the history of JavaScript and how it came into existence. To cut the long story short, ECMA in ECMAScript refers to Europen Computer Manufacturers Association to which JavaScript 1.1 was submitted for standardization back in the year 1997.

Data Types In JavaScript

JavaScript data types are kept easy. While JavaScript data types are mostly similar to other programming languages; some of its data types can be unique. Here, we’ll outline the data types of JavaScript.

Forms of Composition in JavaScript and React

One of the core ideas in functional programming is composition: building larger things from smaller things. The canonical example of this idea should be familiar with legos.

JavaScript Memory Management System

The main goal of this article is help to readers to understand that how memory management system performs in JavaScript. I will use a shorthand such as GC which means Garbage Collection. When the browsers use Javascript, they need any memory location to store objects, functions, and all other things. Let’s deep in dive that how things going to work in GC.