PureComponent and React.memo
As React applications grow in complexity, performance optimization becomes a priority to prevent performance decline. React provides two ways to prevent unnecessary re-renders: PureComponent for class components, and React.memo for functional components.
In this tutorial, we’ll learn how to memoize components in React using React.PureComponent and the React.memo API. We’ll cover some of the fundamentals of React components before we dive into an example.
You can keep up with the changes and suggestions for the React framework on the React RFCs repository.
The Replay is a weekly newsletter for dev and engineering leaders.
Delivered once a week, it's your curated guide to the most important conversations around frontend dev, emerging AI tools, and the state of modern software.
Like most modern JavaScript frameworks, React is component-based. A component is usually defined as a function of its state and props.
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>
)
}
}
// FUNCTIONAL COMPONENT
function ReactHeader(props) {
return (
<h1>
React {props.version || 17} Documentation
</h1>
)
}
Editor’s note: This post was updated by Chizaram Ken in March 2025 to compare and contrast the use of PureComponent and the more modern React.memo.
React components tend to re-render frequently during normal application usage. This behavior can occur when props change, state updates, or parent components re-render.
Without proper optimization, these re-renders can become unnecessary and impact performance — especially in large applications with complex component trees, and when components must handle frequent data updates.
Based on the concept of purity in functional programming paradigms, a function is said to be pure if it meets the following two conditions:
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 because React implements the shouldComponentUpdate() method for them with a shallow comparison of props and state.
When a parent component re-renders, PureComponent performs two key comparisons. It compares the current props with the next props, and compares the current state with the next state.
If neither props nor state has changed (based on shallow comparison), React skips the re-render process entirely. This automatic optimization helps prevent unnecessary renders and improves application performance. In practice, a React pure component looks like the following:
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;
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 because, 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>
)
}
}
React stateless function components are functions that do not manage any state. They are a simple way to define components that don’t need to manage state or lifecycle methods.
In essence, stateless function components are JavaScript functions that return React items after receiving props as input. Stateless functional components are used when a component doesn’t need to maintain its own state or lifecycle methods.
Typically, these components have consistent output based on their inputs because they have no state or side effects.
If you give a stateless function component a set of props, it will always render the same JSX. A simple example is:
const Title = ({ title }) => {
return <h1>{title}</h1>;
};
While functional components don’t have direct lifecycle methods, they still go through the same three phases as class components:
useEffect(() => {}, []) This Hook is similar to componentDidMount in class components. The function inside useEffect runs after the component is first rendereduseEffect(() => {}) If you omit the dependency array ([]), useEffect will run after every render (similar to componentDidUpdate)useEffect(() => { return () => {} }) The function returned inside useEffect (the cleanup function) is equivalent to componentWillUnmount in class components and is used to clean up resources when the component unmounts or before it re-rendersNote that useEffect is not a direct equivalent to lifecycle methods, but rather a different paradigm for handling side effects in your components.
Function components are a simpler way to write components in React. They are JavaScript functions that accept props and return React elements as earlier said.
Here’s a basic example:
const ProductCard = ({ name, price, description, inStock }) => {
return (
<div>
<h2>{name}</h2>
<p>{description}</p>
<span>${price}</span>
<p>{inStock ? 'In Stock' : 'Out of Stock'}</p>
</div>
);
};
The term “stateless function components,” has been outdated since the introduction of Hooks. Modern function components can handle a lot of things, including managing state using useState, handling side effects using useEffect, accessing context, and maintaining references with useRef.
{ pure } HOC from RecomposeIn the past, optimizing a functional component so that React could treat it as a pure component wasn’t going to necessarily require that you convert the component to a class component.
The Recompose package then provides a broad collection of higher-order components (HOCs) that are very useful for dealing with functional components. This 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);
However, the Recompose library is no longer a recommended approach to optimizing React components because it has been officially deprecated. Its functionality has been largely replaced by React Hooks, which effectively addresses the same issues.
React now provides us with React.memo as the official way to optimize a functional component.
React.memoFunctional components in React can now leverage similar performance optimizations as PureComponent through the use of React.memo Hook. While functional components don’t inherently skip re-renders, they can be wrapped with memo to achieve the same optimization.
With React.memo, you can create memoized functional components that prevent unnecessary updates. This functionality is particularly useful when dealing with components that receive the same set 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);
It is important to note that, unlike PureComponent, memo only compares props. However, in functional components, calling the state setter with the same state already prevents re-renders by default, even without memo.
React.memo API implementation detailsThere 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 React.memo.
React.memo also works with components rendered from the server using ReactDOMServer.
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,. It returns false when the props are not equal.
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 comparisons.
The arePropsEqual() function acts very similar to the shouldComponentUpdate() lifecycle method in class components. Note that arePropsEqual works in the opposite way:
shouldComponentUpdate — Returns true to trigger a re-renderarePropsEqual — Returns true to prevent a re-renderPureComponent class component to a functionIt is important to emphasize strongly that class components are no longer recommended in new code. Although React still supports class components, the recommended approach is to use functional components.
Here’s how to convert a PureComponent class to a modern function component using React.memo.
PureComponent version:
import { PureComponent } from 'react';
class Greeting extends PureComponent {
render() {
console.log("Greeting was rendered at", new Date().toLocaleTimeString());
return <h3>Hello{this.props.name && ', '}{this.props.name}!</h3>;
}
}
Converted function component with memo:
import { memo } from 'react';
const Greeting = memo(function Greeting({ name }) {
console.log("Greeting was rendered at", new Date().toLocaleTimeString());
return <h3>Hello{name && ', '}{name}!</h3>;
});
The functional component version achieves the same optimization, but it’s more concise and follows modern React practices.
PureComponent and React.MemoBelow is a brief comparison of pureComponent and React.Memo:
| Features | PureComponent |
React.memo |
|---|---|---|
| State handling | Compares both props and state | Only compares props; state changes are automatically optimized |
| Props access | Through this.props |
Directly as function parameters |
| Import statement | import { PureComponent } from 'react' |
import { memo } from 'react' |
| Component definition | class MyComponent extends PureComponent |
const MyComponent = memo(function MyComponent) |
| Lifecycle methods | Uses class lifecycle methods | Uses hooks for lifecycle functionality |
| Syntax | More verbose; requires class syntax | More concise; uses function syntax |
| Performance optimization | Automatic shallow comparison | Customizable comparison through second argument |
| State declaration | this.state = { ... } |
Uses useState Hook |
| Modern React alignment | Depreacted approach | Recommended modern approach |
As developers, knowing when to use a tool is important. It either tells on your optimization or makes your code unnecessarily verbose. Having said this, I will briefly point out when to use memoization and when you really shouldn’t bother about it:
With React.memo API, you can now enjoy the performance benefits that come from using functional components together with the optimizations that come with memoizing the components.
In this article, we covered the React.memo API in detail. First, we covered the differences between functional and class components in React, and then we reviewed pure components, learned how to convert a functional component to a class component, and covered how to convert a class component to a functional component.
I hope you enjoyed this article. Be sure to leave a comment if you have any questions. Happy coding!

Vibe coding isn’t just AI-assisted chaos. Here’s how to avoid insecure, unreadable code and turn your “vibes” into real developer productivity.

GitHub SpecKit brings structure to AI-assisted coding with a spec-driven workflow. Learn how to build a consistent, React-based project guided by clear specs and plans.

:has(), with examplesThe CSS :has() pseudo-class is a powerful new feature that lets you style parents, siblings, and more – writing cleaner, more dynamic CSS with less JavaScript.

Kombai AI converts Figma designs into clean, responsive frontend code. It helps developers build production-ready UIs faster while keeping design accuracy and code quality intact.
Would you be interested in joining LogRocket's developer community?
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 now
7 Replies to "Pure components in React: Using <code>PureComponent</code> and <code>React.memo</code>"
“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.
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.
Good article, thanks.
Well explained details in the article, I managed to solve a performance issue based on this post!
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
React is a library not a framework
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.