PureComponent and React.memo

Pure components and React.memo are essential tools in React.js for optimizing performance by preventing unnecessary re-renders. This chapter will cover the concepts from basic to advanced, providing detailed explanations and examples to ensure a comprehensive understanding.

What is a Pure Component?

A Pure Component in React is a component that performs a shallow comparison of its props and state to determine whether the component should re-render. If the props and state have not changed, the component does not re-render, which can improve performance.

				
					import React, { PureComponent } from 'react';

class MyComponent extends PureComponent {
    render() {
        console.log('MyComponent render');
        return <div>{this.props.value}</div>;
    }
}

export default MyComponent;

				
			

In this example, MyComponent will only re-render if its props.value changes.

What is React.memo?

React.memo is a higher-order component that memoizes a functional component. It behaves similarly to PureComponent but is used with functional components.

				
					import React from 'react';

const MyComponent = React.memo(({ value }) => {
    console.log('MyComponent render');
    return <div>{value}</div>;
});

export default MyComponent;

				
			

In this example, MyComponent will only re-render if its props.value changes.

Why Use Pure Component and React.memo?

Using Pure Component and React.memo can significantly improve the performance of a React application by reducing unnecessary re-renders. This is particularly useful in large applications with complex component trees.

How Pure Component Works

Pure Component performs a shallow comparison of the current and previous props and state. If all props and state are equal (shallow comparison), the component does not re-render.

				
					import React, { PureComponent } from 'react';

class MyComponent extends PureComponent {
    render() {
        console.log('MyComponent render');
        return <div>{this.props.value}</div>;
    }
}

class App extends React.Component {
    state = {
        value: 0
    };

    increment = () => {
        this.setState({ value: this.state.value + 1 });
    };

    render() {
        return (
            <div>
                <MyComponent value={this.state.value} />
                <button onClick={this.increment}>Increment</button>
            </div>
        );
    }
}

export default App;

				
			

Explanation

  • When the button is clicked, the value in the state is incremented.
  • MyComponent only re-renders if this.state.value changes, as it performs a shallow comparison of props.

How React.memo Works

React.memo works by memoizing the functional component. It performs a shallow comparison of the current and previous props. If all props are equal (shallow comparison), the component does not re-render.

				
					import React, { useState } from 'react';

const MyComponent = React.memo(({ value }) => {
    console.log('MyComponent render');
    return <div>{value}</div>;
});

function App() {
    const [value, setValue] = useState(0);

    const increment = () => {
        setValue(value + 1);
    };

    return (
        <div>
            <MyComponent value={value} />
            <button onClick={increment}>Increment</button>
        </div>
    );
}

export default App;

				
			

Explanation

  • When the button is clicked, the value in the state is incremented.
  • MyComponent only re-renders if value changes, as it performs a shallow comparison of props.

Differences Between Pure Component and React.memo

  • Class vs. Functional: Pure Component is used with class components, while React.memo is used with functional components.
  • Shallow Comparison: Both perform a shallow comparison of props and state to determine if a re-render is necessary.

Usage:

  • Pure Component: class MyComponent extends PureComponent { ... }
  • React.memo: const MyComponent = React.memo(function MyComponent(props) { ... })

Practical Examples

Example 1: Using Pure Component

				
					import React, { PureComponent } from 'react';

class PureChild extends PureComponent {
    render() {
        console.log('PureChild render');
        return <div>Pure Component: {this.props.value}</div>;
    }
}

class App extends React.Component {
    state = {
        value: 0
    };

    increment = () => {
        this.setState({ value: this.state.value + 1 });
    };

    render() {
        return (
            <div>
                <PureChild value={this.state.value} />
                <button onClick={this.increment}>Increment</button>
            </div>
        );
    }
}

export default App;

				
			

Output

  • PureChild render is logged only when the value prop changes.
  • Clicking “Increment” increments the value and re-renders PureChild.

Example 2: Using React.memo

				
					import React, { useState } from 'react';

const MemoChild = React.memo(({ value }) => {
    console.log('MemoChild render');
    return <div>Memo Component: {value}</div>;
});

function App() {
    const [value, setValue] = useState(0);

    const increment = () => {
        setValue(value + 1);
    };

    return (
        <div>
            <MemoChild value={value} />
            <button onClick={increment}>Increment</button>
        </div>
    );
}

export default App;

				
			

Output:

  • MemoChild render is logged only when the value prop changes.
  • Clicking “Increment” increments the value and re-renders MemoChild.

Advanced Topics

Custom Comparison Functions with React.memo

By default, React.memo performs a shallow comparison of props. You can provide a custom comparison function to control the behavior.

				
					import React, { useState } from 'react';

const MemoChild = React.memo(
    ({ value }) => {
        console.log('MemoChild render');
        return <div>Memo Component: {value}</div>;
    },
    (prevProps, nextProps) => {
        // Custom comparison: only re-render if value is an even number
        return prevProps.value % 2 === nextProps.value % 2;
    }
);

function App() {
    const [value, setValue] = useState(0);

    const increment = () => {
        setValue(value + 1);
    };

    return (
        <div>
            <MemoChild value={value} />
            <button onClick={increment}>Increment</button>
        </div>
    );
}

export default App;

				
			

Explanation

  • MemoChild re-renders only if value changes from even to odd or vice versa.
  • Custom comparison function enhances control over re-rendering.

Performance Considerations

While Pure Component and React.memo can improve performance, they can also introduce overhead due to shallow comparisons. Use them judiciously, especially in large component trees or when dealing with deeply nested objects.

Common Pitfalls and Best Practices

  • Avoid Overuse: Not every component needs to be a Pure Component or memoized. Use these tools for components that have frequent re-renders with unchanged props.
  • State and Props: Ensure that state and props are immutable and updated properly to benefit from shallow comparisons.
  • Custom Comparison Functions: Use custom comparison functions with React.memo for complex comparison logic, but be cautious of the performance implications.

Summary

  • Pure Component: A class component that performs shallow comparisons of props and state to prevent unnecessary re-renders.
  • React.memo: A higher-order component for memoizing functional components, preventing re-renders with unchanged props.
  • Usage: Use Pure Component for class components and React.memo for functional components.
  • Advanced Control: Custom comparison functions with React.memo provide fine-grained control over re-renders.
  • Best Practices: Use judiciously, ensure immutability, and avoid overuse to optimize performance effectively.

Example 1: Using Pure Component

In this example, we’ll create a simple app that displays a list of users and a counter. The user list component will be a Pure Component to prevent unnecessary re-renders when the counter updates.

Components

  1. UserList: A Pure Component that displays a list of users.
  2. App: The main component that manages the state and renders the UserList and a counter.
				
					import React, { PureComponent, Component } from 'react';

// PureComponent to display a list of users
class UserList extends PureComponent {
    render() {
        console.log('UserList render');
        const { users } = this.props;
        return (
            <div>
                <h2>User List</h2>
                <ul>
                    {users.map(user => (
                        <li key={user.id}>{user.name}</li>
                    ))}
                </ul>
            </div>
        );
    }
}

class App extends Component {
    state = {
        users: [
            { id: 1, name: 'John Doe' },
            { id: 2, name: 'Jane Smith' },
            { id: 3, name: 'Jack Johnson' }
        ],
        counter: 0
    };

    incrementCounter = () => {
        this.setState({ counter: this.state.counter + 1 });
    };

    render() {
        return (
            <div>
                <UserList users={this.state.users} />
                <div>
                    <h2>Counter: {this.state.counter}</h2>
                    <button onClick={this.incrementCounter}>Increment Counter</button>
                </div>
            </div>
        );
    }
}

export default App;

				
			

Explanation

  • UserList: This is a Pure Component that receives a list of users as props. It only re-renders if the users prop changes.
  • App: The main component manages the state of the users and the counter. When the counter is incremented, the UserList component does not re-render because the users prop has not changed.

Output

  • When you click the “Increment Counter” button, the counter updates, but the UserList component does not re-render, as indicated by the absence of “UserList render” in the console.

Example 2: Using React.memo

In this example, we’ll create a simple app that displays a list of products and a search bar. The product list component will use React.memo to prevent unnecessary re-renders when the search query updates.

Components

  1. ProductList: A memoized functional component that displays a list of products.
  2. App: The main component that manages the state and renders the ProductList and a search bar.
				
					import React, { useState, memo } from 'react';

// Memoized functional component to display a list of products
const ProductList = memo(({ products }) => {
    console.log('ProductList render');
    return (
        <div>
            <h2>Product List</h2>
            <ul>
                {products.map(product => (
                    <li key={product.id}>{product.name}</li>
                ))}
            </ul>
        </div>
    );
});

function App() {
    const [products] = useState([
        { id: 1, name: 'Laptop' },
        { id: 2, name: 'Smartphone' },
        { id: 3, name: 'Tablet' }
    ]);
    const [search, setSearch] = useState('');

    const handleSearchChange = (e) => {
        setSearch(e.target.value);
    };

    return (
        <div>
            <input
                type="text"
                value={search}
                onChange={handleSearchChange}
                placeholder="Search products..."
            />
            <ProductList products={products} />
        </div>
    );
}

export default App;

				
			

Explanation

  • ProductList: This is a memoized functional component that receives a list of products as props. It only re-renders if the products prop changes.
  • App: The main component manages the state of the products and the search query. When the search query is updated, the ProductList component does not re-render because the products prop has not changed.

Output

  • When you type in the search bar, the search query updates, but the ProductList component does not re-render, as indicated by the absence of “ProductList render” in the console.

Pure Component and React.memo are powerful tools in React.js that help optimize performance by preventing unnecessary re-renders. By understanding how they work and applying best practices, you can build more efficient and responsive React applications.Happy coding !❤️

Table of Contents

Contact here

Copyright © 2025 Diginode

Made with ❤️ in India