← Back to Chapters

Pure Components and React.PureComponent

⚛️ Pure Components and React.PureComponent

? Performance Optimization

? Quick Overview

A Pure Component is a special kind of React component that automatically skips unnecessary re-renders by doing a shallow comparison of its props and state.

  • Re-renders only when props or state actually change (shallow comparison).
  • Helps improve performance, especially in medium/large React applications.
  • Implemented using React.PureComponent for class components and React.memo() for functional components.

? Key Concepts

  • Regular Component: Re-renders whenever its parent re-renders, even if props are the same.
  • Pure Component: Extends React.PureComponent and skips rendering when props/state are shallowly equal.
  • Shallow Comparison: Compares primitive values directly and object references (not deep equality).
  • Functional Equivalent: React.memo() wraps a functional component and gives PureComponent-like behavior.

?️ Regular Component vs Pure Component

In a normal React Component, the child re-renders whenever the parent re-renders, even if the received props are exactly the same.

A Pure Component (via React.PureComponent) automatically checks previous vs new props/state with a shallow comparison and only re-renders when something actually changes.

? View Code Example: Regular vs Pure Component
// Regular class component - always re-renders when parent renders
import React, { Component, PureComponent } from "react";

class RegularComponent extends Component {
  render() {
    console.log("Regular Component rendered");
    return <h3>Regular: {this.props.name}</h3>;
  }
}

// Pure component - skips render when props/state are shallowly equal
class PureComp extends PureComponent {
  render() {
    console.log("Pure Component rendered");
    return <h3>Pure: {this.props.name}</h3>;
  }
}

export { RegularComponent, PureComp };

? Example: Comparing Both

Here is a parent component that updates state with the same value every 2 seconds. This lets us see how Regular vs Pure Components behave.

? View Code Example: Parent Comparing Components
// Parent component to compare RegularComponent and PureComp
import React, { Component } from "react";
import { RegularComponent, PureComp } from "./ChildComponents";

class ParentComp extends Component {
  constructor(props) {
    super(props);
    this.state = { name: "React" };
  }

  componentDidMount() {
    setInterval(() => {
      // State is updated with the SAME value - no "real" change
      this.setState({ name: "React" });
    }, 2000);
  }

  render() {
    console.log("Parent rendered");
    return (
      <div>
        <h2>Parent Component</h2>
        <RegularComponent name={this.state.name} />
        <PureComp name={this.state.name} />
      </div>
    );
  }
}

export default ParentComp;

?️ Live Output / Console Behavior

  • ⏱️ Every 2 seconds, ParentComp calls setState with the same value.
  • ? RegularComponent re-renders on every parent render, even when name is unchanged.
  • PureComp skips re-render because the shallow comparison sees no change in name.

In the browser console you will see multiple logs:

  • "Parent rendered" every 2 seconds.
  • "Regular Component rendered" every 2 seconds.
  • "Pure Component rendered" only for the first render (and whenever props actually change).

⚙️ How Does React.PureComponent Work?

  • React.PureComponent implements shouldComponentUpdate() with a shallow comparison.
  • If previous vs next props and state are shallowly equal, React skips the render.
  • Shallow comparison checks:
    • Primitives (string, number, boolean) by value.
    • Objects/arrays by reference (same pointer in memory).
  • If you mutate nested objects in-place, PureComponent might not detect the change.
? View Code Example: Shallow Comparison Reminder
// Bad pattern: mutating nested state object in-place
this.state = { user: { name: "Alex" } };

// Later in code
const user = this.state.user;
user.name = "Sam";            // Same object reference - shallow compare thinks "no change"
this.setState({ user });      // PureComponent may SKIP the re-render here

? Pure Components in Functional Components (React.memo)

For functional components, the equivalent optimization is React.memo(). It wraps a component and re-renders it only when its props change (again, using shallow comparison by default).

? View Code Example: React.memo()
// Functional child wrapped with React.memo for Pure-like behavior
import React from "react";

const Child = ({ value }) => {
  console.log("Child rendered");
  return <p>Value: {value}</p>;
};

const MemoizedChild = React.memo(Child);

export default MemoizedChild;

? Explanation

When you use MemoizedChild, React will only re-render it if the value prop changes (based on shallow comparison). If the parent re-renders without changing value, the memoized child is skipped.

⚠️ When to Avoid Pure Components

  • ❌ When using deeply nested objects that are updated by mutation instead of immutably.
  • ❌ When the component is extremely small and simple (no visible performance benefit).
  • ❌ When props or state are always changing (no render can be skipped).
  • ❌ When the shallow comparison cost is higher than the render cost (rare but possible).

? Tips & Best Practices

  • Use React.PureComponent for class components that depend heavily on props/state.
  • Use React.memo() for functional components needing the same optimization.
  • Keep props immutable: avoid mutating arrays/objects in-place.
  • Lift complex calculations out of render, or memoize them, to maximize the benefit.
  • Measure before and after using DevTools to confirm that PureComponent actually helps.

? Try It Yourself

  1. Create a ParentComp with both RegularComponent and PureComp.
  2. Use setInterval to repeatedly call setState with the same value.
  3. Open the browser console and observe:
    • RegularComponent logs on every interval.
    • PureComp logs only when the value truly changes.
  4. Convert one of the children into a functional component and wrap it with React.memo().
  5. Experiment with:
    • Passing primitive props (numbers, strings).
    • Passing objects/arrays and mutating vs creating new references.

Goal: Understand how React.PureComponent and React.memo() skip unnecessary re-renders and improve React performance.