Glad Chinda Full-stack web developer learning new hacks one day at a time. Web technology enthusiast. Hacking stuffs @theflutterwave.

Pure functional components in React

5 min read 1442

React Pure Functional Components

Editor’s note: This post was updated on 28 December 2020.

React is an open source JavaScript library for building user interface components. One of the most popular frontend libraries of 2020, React has almost 3 million users and a massive developer community and runs on a wide range of platforms, from the web to mobile devices.

In this tutorial, we’ll focus on pure functional components in React and show you how to use React.PureComponent and the React.memo() API to memoize functional components in React.

We’ll cover the following in detail:

You can keep up with the changes and suggestions for the React framework on the React RFCs repository.

What are React components?

Like most modern JavaScript frameworks, React is component-based. In React terms, a component is usually defined as a function of its state and props.

Functional components vs. class components

React supports two flavors of components: class components and functional components. A functional component is a plain JavaScript function that returns JSX. A class component is a JavaScript class that extends React.Component and returns JSX inside a render method.

The following code snippet shows a simple ReactHeader component defined as both a class component and a functional component:

// CLASS COMPONENT
class ReactHeader extends React.Component {
  render() {
    return (
      <h1>
        React {this.props.version || 16} Documentation
      </h1>
    )
  }
}


// FUNCTIONAL COMPONENT
function ReactHeader(props) {
  return (
    <h1>
      React {props.version || 16} Documentation
    </h1>
  )
}

For a refresher on React functional components, check out this video tutorial:

We made a custom demo for .
No really. Click here to check it out.

What is a React pure component?

Based on the concept of purity in functional programming paradigms, a function is said to be pure if:

  • Its return value is only determined by its input values
  • Its return value is always the same for the same input values

A React component is considered pure if it renders the same output for the same state and props. For class components like this, React provides the PureComponent base class. Class components that extend the React.PureComponent class are treated as pure components.

Pure components have some performance improvements and render optimizations since React implements the shouldComponentUpdate() method for them with a shallow comparison for props and state.

How does a React pure component work?

In practice, a React pure component looks like this:

import React from 'react';

class PercentageStat extends React.PureComponent {

  render() {
    const { label, score = 0, total = Math.max(1, score) } = this.props;

    return (
      <div>
        <h6>{ label }</h6>
        <span>{ Math.round(score / total * 100) }%</span>
      </div>
    )
  }

}

export default PercentageStat;

Are React functional components pure?

Functional components are very useful in React, especially when you want to isolate state management from the component. That’s why they are often called stateless components.

However, functional components cannot leverage the performance improvements and render optimizations that come with React.PureComponent since they are not classes by definition.

If you want React to treat a functional component as a pure component, you’ll have to convert the functional component to a class component that extends React.PureComponent.

Here’s a simple example:

// FUNCTIONAL COMPONENT
function PercentageStat({ label, score = 0, total = Math.max(1, score) }) {
  return (
    <div>
      <h6>{ label }</h6>
      <span>{ Math.round(score / total * 100) }%</span>
    </div>
  )
}


// CONVERTED TO PURE COMPONENT
class PercentageStat extends React.PureComponent {

  render() {
    const { label, score = 0, total = Math.max(1, score) } = this.props;

    return (
      <div>
        <h6>{ label }</h6>
        <span>{ Math.round(score / total * 100) }%</span>
      </div>
    )
  }

}

Using the { pure } HOC from Recompose

Optimizing a functional component so that React can treat it as a pure component shouldn’t necessarily require that the component be converted to a class component.

If you are already familiar with the Recompose package, then you know that it provides a wide collection of higher-order components (HOCs) that makes it very useful when dealing with functional components.

The Recompose package exports a { pure } HOC that tries to optimize a React component by preventing updates on the component unless a prop has changed, using shallowEqual() to test for changes.

Using the pure HOC, our functional component can be wrapped as follows:

import React from 'react';
import { pure } from 'recompose';

function PercentageStat({ label, score = 0, total = Math.max(1, score) }) {
  return (
    <div>
      <h6>{ label }</h6>
      <span>{ Math.round(score / total * 100) }%</span>
    </div>
  )
}

// Wrap component using the `pure` HOC from recompose
export default pure(PercentageStat);

Ensure components render in production

Debugging React applications can be difficult, especially when there is complex state. If you’re interested in monitoring and tracking Redux state for all of your users in production, try LogRocket.

LogRocket is like a DVR for web apps, recording literally everything that happens on your site. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your React apps — .

React.memo(): A brief history

In October 2018, Dan Abramov of the core React team tweeted about some additional features that were undergoing review for the next minor release of React:

One of the new features was the React.pure() API, which optimized functional components in a way similar to optimizing class components using React.PureComponent.

Naming the API pure() led to confusion with the concept of pure functions in functional programming. Since it basically memoizes functional components, the React community decided to rename it to React.memo() with the release of React v16.6 in 2018 (the most recent version of React at the time of writing is React v17).

How to use React.memo()

With React.memo(), you can create memoized functional components that bail out of rendering on unnecessary updates using shallow comparison of props.

Using the new React.memo() API, the previous functional component can be wrapped as follows:

import React, { memo } from 'react';

function PercentageStat({ label, score = 0, total = Math.max(1, score) }) {
  return (
    <div>
      <h6>{ label }</h6>
      <span>{ Math.round(score / total * 100) }%</span>
    </div>
  )
}

// Wrap component using `React.memo()`
export default memo(PercentageStat);

Implementation details

There are a few things worth knowing about the implementation of the React.memo() API:

  1. React.memo() is a higher-order component. It takes a React component as its first argument and returns a special kind of React component
  2. React.memo() returns a special React component type. That allows the renderer to render the component while memoizing the output — thus, bailing out of updates if the component’s props are shallowly equal
  3. React.memo() works with all React components. The first argument passed to React.memo() can be any type of React component. However, for class components, you should use React.PureComponent instead of using React.memo()
  4. React.memo() also works with components rendered from the server using ReactDOMServer

Custom bailout condition

The React.memo() API can take a second argument, which is the arePropsEqual() function. The default behavior of React.memo() is to shallowly compare the component props. However, with the arePropsEqual() function, you can customize the bailout condition for component updates. The arePropsEqual() function is defined with two parameters: prevProps and nextProps. The arePropsEqual() function returns true when the props are compared to be equal (thereby preventing the component from re-rendering) and returns false when the props are not equal. The arePropsEqual() function acts much like the shouldComponentUpdate() lifecycle method in class components, but in the reverse manner. The following code snippet uses a custom bailout condition:

import React, { memo } from 'react';

function PercentageStat({ label, score = 0, total = Math.max(1, score) }) {
  return (
    <div>
      <h6>{ label }</h6>
      <span>{ Math.round(score / total * 100) }%</span>
    </div>
  )
}

function arePropsEqual(prevProps, nextProps) {
  return prevProps.label === nextProps.label; 
}

// Wrap component using `React.memo()` and pass `arePropsEqual`
export default memo(PercentageStat, arePropsEqual);

Conclusion

With the React.memo() API, you can enjoy the performance benefits that come with using functional components together with optimizations that come with memoizing the components.

Glad Chinda Full-stack web developer learning new hacks one day at a time. Web technology enthusiast. Hacking stuffs @theflutterwave.

Testing accessibility with Storybook

One big challenge when building a component library is prioritizing accessibility. Accessibility is usually seen as one of those “nice-to-have” features, and unfortunately, we’re...
Laura Carballo
4 min read

6 Replies to “Pure functional components in React”

  1. “Speaking about JavaScript frameworks at such a time as this can never be complete if nothing is said about the React framework created and maintained by the team at Facebook.”

    React is not a framework, it’s a UI-library for creating re-usable components.

    1. You’re technically right, but it’s a meaningless distinction IMO. If you’d like to write a post for the blog explaining why it’s not a meaningless distinction, I’d be happy to publish it.

  2. Well explained details in the article, I managed to solve a performance issue based on this post!

  3. Why we call react a framework ?
    Is it because it became so popular, that it replaced angular in many real world projects…
    angular is framework, so we call react also a framework

  4. Appreciate the way this article explains. I have been searching for “how to write pure components wo using class”. hardly any articles available.. This is very well articulated.
    Thanks.

Leave a Reply