Sunil Sandhu Software Engineer, Editor of JavaScript In Plain English (JSIPE)

3 advantages of React functional components on an eCommerce site

4 min read 1216


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!


Plug: LogRocket, a DVR for web apps

https://logrocket.com/signup/

LogRocket is a frontend logging tool that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single page apps.

Try it for free.

Sunil Sandhu Software Engineer, Editor of JavaScript In Plain English (JSIPE)

Leave a Reply