Lesson 31 +10 XP

React Performance & React.memo

React Performance & React.memo

By default, when a parent component re-renders, all of its child components re-render recursively, regardless of whether their props have actually changed. For large UI trees, unnecessary re-renders can degrade rendering performance.

Understanding Component Re-rendering Behavior

React components re-render for three main reasons:

  1. Local component state changes.
  2. Component props change.
  3. Parent component re-renders.

Even if a child component receives no props, it will re-render whenever its parent re-renders unless memoized.

Skipping Re-renders with React.memo

React.memo is a Higher-Order Component (HOC) that memoizes a component. It skips re-rendering the component if its props have not changed since the last render.

import React, { useState } from 'react';

// Child component wrapped in React.memo
const ExpensiveChild = React.memo(function ExpensiveChild({ name }) {
  console.log("ExpensiveChild rendered!");
  return <div>Hello, {name}</div>;
});

function Parent() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>
        Parent Counter: {count}
      </button>
      {/* ExpensiveChild will NOT re-render when 'count' changes! */}
      <ExpensiveChild name="Alice" />
    </div>
  );
}

Shallow Prop Comparison

React.memo performs a shallow comparison of props using Object.is.

  • Primitive props (numbers, strings, booleans) compare by value.
  • Reference types (objects, arrays, functions) compare by memory address reference!

If a parent component passes a newly created object literal (style={{ color: 'red' }}) or inline function (onClick={() => ...}) to a memoized child, the memory reference changes on every render, causing React.memo shallow comparison to fail and re-render anyway!

Summary & TL;DR

  • Parent re-renders cause all child components to re-render by default.
  • React.memo(Component) prevents re-renders if props have not changed.
  • Uses shallow comparison for props—passing new object/function references invalidates memoization.