If you’ve used React before, chances are that you’ve had to require some form of method for managing things.
If we take, for example, an ecommerce site, it’s likely that your application is going to have to look after a variety of things, such as what items are in stock, and what items a user has added to their shopping cart. These require state management, which leads us — in React — to use class-based components.
An example of a class-based component for our ecommerce store may look something like this:
class App extends Component {
constructor(props) {
super(props);
this.state = {
items: [
{
id: 0,
name: ‘Banana’
price: 25,
stock: 2
},
{
id: 0,
name: ‘Pineapple’
price: 90,
stock: 5
},
{
id: 0,
name: ‘Orange’
price: 20,
stock: 8
},
{
id: 0,
name: ‘Apple’
price: 50,
stock: 1
},
],
cart: [],
total: 0,
}
}
}
So far, this makes sense. But what about the components in our app that simply handle presentation and do not require any internal state?
Well, that’s where we can start to use functional components instead.
Continuing on with our ecommerce example, each product that we show in the app is likely to be its own component — let’s refer to this component as Product.js.
Now inside of Product.js, there may very well be smaller sub-components, such as buttons that can be clicked on to add/remove items to the shopping cart.
Let’s examine a component we may have called ProductAdd.js, which is used to add a product to the shopping cart. Now we may initially, out of habit, look to create a class component for this button which could look something like this:
import React, {Component} from ‘react’;
class ProductAdd extends Component {
render() {
return (
<button onClick={(e) => this.props.addToCart(this.props.id)}> + </button>
);
}
}
export default ProductAdd;
It’s not the end of the world if we write this, but given that it requires no internal state, we could rewrite this as a functional component instead. It would then end up looking something like this:
import React from ‘react’;
const ProductAdd = (props) => {
return (
<button onClick={(e) => props.addToCart(props.id)}>+</button>
);
}
export default ProductAdd;
One thing you may also notice here is that we are still able to pass props to the component which can be in the form of either data or a function.
So with the exception of handling the internal state of a component, functional components can do the same things that a class component can do.
With the example we’ve used here, we could decide to go even further up the chain and rewrite our Product.js as a functional component, as the state of the file would have been passed down from the main App.js file that we showed at the start of the article. So there’s quite a bit of refactoring that we could be doing here.
But given that our entirely class-based component application is working just fine, why would we bother taking the time to refactor?
Let’s take a look at three reasons why.
1. No Class means no ‘this’
It’s always advantageous if you don’t have to use ‘this’ when writing your Javascript code. And fine, you may be reading this and feel that you already have a good enough grasp of the ‘this’ keyword. But when it comes to debugging and overall readability, not having to reason about the scope of ‘this’ is always a plus.
We’ve all had moments in time where we’ve had to debug something in React and found that some part of our app wasn’t working as expected because we’d referred to a bit of state as something
, rather than this.something
. The issue of this is non-existent with functional components.
And to add another bonus, not having to use this means that we also don’t have to use bind, which is an even more confusing concept to wrap your head around. So two fewer things to wrap your head around, which means two fewer tangles, which means cleaner, clearer code. Win win!
2. Fewer lines = better performance
As you may have noticed from our ProductAdd functional component, it had two fewer lines than our class-based equivalent. The two fewer lines here were a result of us not having to wrap our JSX inside of a render()
function.
Two fewer lines may not seem like much here, but if you have an ecommerce site, where each product is its own component, we could quite easily have in excess of 1000 components. So those two fewer lines would total up to 2000 lines saved!
Another plus to this is that the fewer lines of code a developer has to read and write, the quicker and easier their code is to understand.
Now besides the obvious improvement of potentially using fewer lines of code when using a stateless functional component, it’s been well documented that functional components in React (as of Oct 2018) do not provide an improvement in terms of internal performance.
However, it has been equally well documented that stateless functional components may soon offer improved performance in future iterations of React. This boost will be the result of there being no state or lifecycle methods to worry about.
So with this in mind, it’s worth getting used to using them now as a means of future-proofing your codebase and general understanding of React best practices.
Nevertheless, functional components still transpile down to less code than class components, which means functional components = smaller bundles.
3. Easier to read, easier to understand, easier to reason about, easier to test
As we have seen, stateless functional components are simply functions that return JSX. Because there is no state being manipulated in any way, this makes them easier to read and understand.
Because the component does not rely on any internal state, this means that they’re easier to reason with, as we know that any state being passed into a stateless functional component has arrived in the form of a prop being passed in by a parent component. This means that we can go further up the tree when it comes to debugging.
And ultimately, because these components are simply functions that return JSX, this makes them really easy to test because you are simply looking to assert that a function returns what you want it to.
And there we have it!
There’s three advantages to using functional components and why you should look to add them to your arsenal of tools today!
LogRocket is like a DVR for web and mobile apps and websites, recording literally everything that happens on your ecommerce app. Instead of guessing why users don’t convert, LogRocket proactively surfaces the root cause of issues that are preventing conversion in your funnel, such as JavaScript errors or dead clicks. LogRocket also monitors your app’s performance, reporting metrics like client CPU load, client memory usage, and more.
Start proactively monitoring your ecommerce apps — try LogRocket for free.
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowSOLID principles help us keep code flexible. In this article, we’ll examine all of those principles and their implementation using JavaScript.
JavaScript’s Date API has many limitations. Explore alternative libraries like Moment.js, date-fns, and the new Temporal API.
Explore use cases for using npm vs. npx such as long-term dependency management or temporary tasks and running packages on the fly.
Validating and auditing AI-generated code reduces code errors and ensures that code is compliant.