VOOZH about

URL: https://blog.logrocket.com/pure-component-in-react/

⇱ Pure components in React: Using PureComponent and React.memo - LogRocket Blog


2025-03-03
2219
#react
Glad Chinda
3905
116
👁 Image

See how LogRocket's Galileo AI surfaces the most severe issues for you

No signup required

Check it out

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.

👁 pure components in react using Using PureComponent and React.memo

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.

🚀 Sign up for The Replay newsletter

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.

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

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.


Why is optimization in React important?

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.

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 because React implements the shouldComponentUpdate() method for them with a shallow comparison of props and state.

How does a pure component work?

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;

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

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.


Over 200k developers use LogRocket to create better digital experiences

👁 Image
Learn more →

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:

  1. Mounting  useEffect(() => {}, []) This Hook is similar to componentDidMount in class components. The function inside useEffect runs after the component is first rendered
  2. Updating  useEffect(() => {}) If you omit the dependency array ([]), useEffect will run after every render (similar to componentDidUpdate)
  3. Unmounting  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-renders

Note that useEffect is not a direct equivalent to lifecycle methods, but rather a different paradigm for handling side effects in your components.

Using React function 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.

Using the { pure } HOC from Recompose

In 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.

How to use React.memo

Functional 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 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 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,. 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.

Comparison with class components

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-render
  • arePropsEqual Returns true to prevent a re-render

Migrating from a PureComponent class component to a function

It 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.

Important differences between PureComponent and React.Memo

Below 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:

  • You will want to memoize components that re-render frequently, and components that receive the same props often
  • You won’t want to memoize simple components (i.e. components that always receive different props), and components that rarely re-render

Conclusion

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!

👁 Image
👁 Image
👁 Image

Stop guessing about your digital experience with LogRocket

Get started for free

Recent posts:

Debug Next.js apps with AI agents and next-browser

Learn how next-browser gives AI agents runtime context for debugging Next.js apps, including React props, hydration, PPR, forms, and performance.

👁 Image
Emmanuel John
Jun 17, 2026 ⋅ 9 min read

Stop hardcoding LLM SDKs: Dynamic LLM routing with OpenRouter and Next.js

Build dynamic LLM routing in Next.js with OpenRouter, TanStack AI, task classification, model fallbacks, and cost-aware routing.

👁 Image
Chizaram Ken
Jun 16, 2026 ⋅ 13 min read

What is TSRX?: What JSX would look like if it were designed today

TSRX adds first-class control flow, conditional hooks, and scoped styles to React via a TypeScript compiler extension — no new framework required.

👁 Image
Ikeh Akinyemi
Jun 12, 2026 ⋅ 6 min read

How to add authentication to a React Native app with Better Auth

Learn how to build a full React Native auth system using Better Auth and Expo — with email/password login, Google OAuth, session persistence, and protected routes.

👁 Image
Chinwike Maduabuchi
Jun 9, 2026 ⋅ 13 min read
View all posts

Hey there, want to help make our blog better?

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