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

What are React pure functional components?

4 min read 1332

React Pure Functional Components

Editor’s note: This post was updated on 23 March 2022 to ensure all packages are up to date.

React is an open source JavaScript library for building user interface components. As one of the most popular frontend libraries of 2021, React has almost 5.7 million users at the time of writing and a massive developer community. React runs on a wide range of platforms, ranging from the web to mobile devices.

In this tutorial, we’ll learn how to memoize functional components in React using React.PureComponent and the React.memo() API. First, we’ll cover some of the fundamentals of React components before we dive into an example. Let’s get started!

Table of contents

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. A component is usually defined as a function of its state and props.

React functional components vs. class components

React supports two types 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 || 17} Documentation
      </h1&gt;
    )
  }
}


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

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

What is a pure component in React?

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

  • 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 this type of class component, 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 pure component work in React?

In practice, a React pure component looks like the following code:

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 by definition, they are not classes.

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.

Check out the simple example below:

// 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 you convert the component to a class component.

The Recompose package provides a broad collection of higher-order components (HOCs) that are very useful for 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);

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 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);

React.memo() API implementation details

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

For one, React.memo() is a higher-order component. It takes a React component as its first argument and returns a special type of React component that allows the renderer to render the component while memoizing the output. Therefore, if the component’s props are shallowly equal, the React.memo() component will bail out the updates.

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(). React.memo() also works with components rendered from the server using ReactDOMServer.

Custom bailout condition

The React.memo() API can take a second argument, 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 it returns false when the props are not equal.



The arePropsEqual() function acts very similar to 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);

We use the strict equal operator === because we want to check the equality between the values and their types without conversion. For example, "1" and 1 are not the same. Loose equality between them will return true, "1" == 1 // true. But, strict equality will be false, "1"=== 1 // false. So, we want to perform strict comparison.

Conclusion

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

In this article, we explored the React.memo() API in detail. First, we covered the differences between functional and class components in React, then we reviewed pure components, learning how to convert a functional component to a class component.

I hope you enjoyed this article, and be sure to leave a comment if you have any questions. Happy coding!

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

7 Replies to “What are React pure functional components?”

  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