Pure components

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 can be 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.

Pure functional components

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

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

In fact, if you have a functional component, and you want React to treat it as a pure component, you will have to convert the functional component to a class component that extends React.PureComponent.

Here is a simple example (still using the PercentageStat component from before):

Using { 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 componentsthat makes it very useful when dealing with functional components.

The recompose package exports a {pure} higher-order component 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 higher-order component, our functional component can be wrapped as follows:

Introducing React.memo() in React 16.6

Although the React framework has gone through several iterations of changes over the years, a couple more improvements and additions are still being made to the framework on a regular basis. You can see the change logs for the framework in the official React repository.

Formerly React.pure()

A few days ago, Dan Abramov from the core React team tweeted about some additional features that were undergoing review for the next minor release of React (v16.6.0).

One of the new features was the React.pure() API, which provides a means of optimizing functional components in a much similar fashion as how class components can be optimized using React.PureComponent.

The React.pure() API is available from React 16.6.0-alpha.400d197. However, it has been changed to React.memo() in React 16.6.

Now React.memo() in React 16.6

Several thoughts went into giving an appropriate name to this new React optimization feature. Naming it pure() will make it to be confused with the concept of pure functions in functional programming, whereas it basically memoizes functional components.

Hence in the final release of React 16.6, the React.pure() API has been renamed as React.memo().

You can checkout the changes and comments about the React.pure()APIon the React RFCsrepository.

Implementation Details

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

React.memo() is a higher-order component. It takes a React component as its first argument and returns a special kind of React component.

React.memo() returns a special React component type — that allows the renderer to render the component while memoizing the output. Hence, bailing out of updates if the component’s props are shallowly equal.

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.

Using React.memo()

With React.memo(), you can now have 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:

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.