React Memo - DH-Learning/MyWiki GitHub Wiki

Memo

React.memo is a higher-order component (HOC) that helps optimize performance in React by preventing unnecessary re-renders of functional components.

What is React.memo?

  • React.memo memoizes the rendered output of a functional component.

  • It re-renders the component only when its props change (using a shallow comparison by default).

  • Think of it as PureComponent for functional components.

Syntax

import React from "react";

const MyComponent = (props) => {
  console.log("Rendering MyComponent");
  return <div>{props.name}</div>;
};

export default React.memo(MyComponent);

Now, MyComponent will not re-render unless props.name changes.

Custom Comparison Function

You can provide a custom comparison function to control re-rendering:

const MyComponent = ({ name, age }) => {
  console.log("Rendering MyComponent");
  return <div>{name} - {age}</div>;
};

function areEqual(prevProps, nextProps) {
  return prevProps.age === nextProps.age; // Only re-render if age changes
}

export default React.memo(MyComponent, areEqual);

When to Use React.memo?

  • Use it for pure functional components that:

    • Render the same output for the same props.

    • Receive frequently changing parent components, but their own props don’t change often.

  • Avoid using it everywhere—it adds overhead because React still needs to compare props.

When NOT to Use React.memo?

  • For components with frequent prop changes (it won’t help).

  • If rendering is cheap, the memoization overhead might be worse than re-rendering.

Note: lets say we have a object as a prop and that object is not changing on the parent re render then also the child component will re render even after wrapping the memo, because on every re render of the parent the reference of the object changes... object will be stored in different locations on every parent render. (vdo link: https://youtu.be/M0c9Inz307Q?si=LR0iPdTXpZgvLD4m)

useMemo Hook

useMemo is a React Hook that helps optimize performance by memoizing a computed value, so that the value is recalculated only when its dependencies change.

Think of useMemo as a way to cache expensive computations between renders.

Syntax

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

  • computeExpensiveValue → A function that returns a value (usually expensive to compute).

  • Dependency array [a, b] → The memoized value is recomputed only when a or b changes.

Why use useMemo?

  • To avoid unnecessary recalculations on every render.

  • Useful when:

    • You have expensive calculations (e.g., filtering, sorting large data).

    • A value is stable across renders unless specific props/state change.

Example Without useMemo

function App({ items }) {
  const [count, setCount] = useState(0);

  // This filtering happens on every render, even when `count` changes
  const filteredItems = items.filter(item => item.includes("a"));

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Increment {count}</button>
      {filteredItems.map(item => <p key={item}>{item}</p>)}
    </div>
  );
}

Here, filteredItems is recalculated every time count changes, even though items hasn’t changed.

Example With useMemo

import { useMemo, useState } from "react";

function App({ items }) {
  const [count, setCount] = useState(0);

  const filteredItems = useMemo(() => {
    console.log("Filtering...");
    return items.filter(item => item.includes("a"));
  }, [items]); // Recompute only when items change

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Increment {count}</button>
      {filteredItems.map(item => <p key={item}>{item}</p>)}
    </div>
  );
}

Now, filteredItems is cached and only recalculated when items changes, not on every count update.

⚠️ **GitHub.com Fallback** ⚠️