Functional Components vs Class Components

When you’re writing React components, you’re faced with a choice. Either functional components, or class components. Do you know what the similarities and the differences are? Which one should you use when? 

Let’s get into it together! 

NOTE: the terms “functional components” and “function components” are both used interchangeably!

Basics of React Functional Components vs Class Components

First, we need to know exactly what we’re talking about when we say function components and class components. 

It’s pretty simple: functional components are … functions, and class components are … classes. Surprising, I know!

But it’s really all there is to it! Sure, they come with different ways of doing things, but if you want to know if a component is a functional or class-based, you just need to look at whether it’s defined as a function or as a class.

TIP: One important requirement for writing both function components and class components is that they need to begin with an uppercase letter. If not, React won’t be happy about it!

What is a class component?

For example, a class component might look like this:

import { Component } from ‘react’; class YourComponent extends Component { render() { return ( <div> <h1>Hello, world!</h1> </div> ); } }

To define a class component, you use the syntax class YourComponent extends Component. “Extending” the Component class provided by React is what makes the class a React Component, rather than just a plain JavaScript class.

You also have to define a render method inside the class, which will be used by React to actually render the component. 

What is a functional component?

What about functional components? Well, you just have to define a function with a name beginning by an uppercase letter and React will know it’s a function component!

As to how to define the function, you have the choices JavaScript gives you. So you can define it using the function keyword:

function YourComponent(props) { return ( <div> <h1>Hello, world!</h1> </div> ); }

But you can also use an arrow function if you want!

const YourComponent = (props) =>; { return ( <div> <h1>Hello, world!</h1> </div> ); }

One specificity of functional components is that you’re using hooks to manage things from state, to lifecycle, to references, and more.

If you want to learn more about react hooks you can check out this article. I also have an article explaining specifically the useRef and the UseReducer Hook which can be tricky!

When should you use which?

Class components are the old way of writing components in React. It’s of course still supported by React, but you can probably expect it to be phased out in the future. 

So most of the time, you’ll want to be using function components rather than class ones.

Of course if you’re working with older code which only (or mostly) has class components, you can totally work with class components! They work just as well. 

There are some advantages to using function components though (that’s why they were introduced and are now favored). Most notably, it’s way cleaner to write functional components than class components. Less code, less complex, less things to think about!

As I said, you can do the same things in function and class components. But there’s one exception to that rule! 

Error Boundaries are a special type of component made for catching errors in your React app. Instead of the app crashing for the user, you can catch the error and display an error screen for example. And Error Boundaries can only be class components!

If you want to learn more about Error Boundaries you can check out the React documentation.

Component lifecycle comparison

An important part of writing React components is their lifecycle. You often want to be doing something when the component first renders, or when something updates, or when the component is unmounted. 

Class components and function components are quite different in how they handle their lifecycle.

Class component lifecycle

In a class component, you access its lifecycle by implementing methods like componentDidMount or componentWillUpdate.

Let’s say you want to implement a timeout in your React class component so that a function is called 1 second after the component first renders.

First, you have to initialize the timeout when the component first mounts:

componentDidMount() { this.timeoutId = setTimeout( () =>; this.doSomething(), 1000 ); }

But you also have to remember to clear the timeout when the components unmounts, otherwise you can get memory leaks that slow down your app! The way you do it is through the componentWillUnmount lifecycle method:

componentWillUnmount() { clearTimeout(this.timeoutId); }

TIP: If you want to know how to do the same thing with function components and hooks, or to understand better how timeouts work, we have a whole article on that!

You can get the whole list of lifecycle methods for class components here.

Functional Component lifecycle

With functional components, all of its lifecycles lives inside one hook, useEffect

The useEffect hook will first run at the beginning of the life of the component, then will run again depending on the dependency array you provided, and then will run its return function at the end of the lifecycle of the component.

useEffect(() =>; { // this will run once at the beginning and then // every time `someVariable` updates console.log(I’m running!) // this will run at the end of the the life of the component return () =>; console.log(‘end of lifecycle’) }, [someVariable])

Conclusion

Class components and function components are capable of doing the same thing, but also have important differences. I hope reading this article cleared those up for you, and you’re ready to tackle writing both class based and functional components!

Avatar photo
👋 Hey, I'm Pierre Ouannes
I’m a Computer Science Engineer with an interest in Web development, Machine Learning and DevOps! I'm currently working as a Full Stack Engineer at Ellipsis Drive, mostly with React. Connect on LinkedIn or Github.

💬 Leave a comment

Your email address will not be published. Required fields are marked *

We will never share your email with anyone else.