memo

Wrap a component in memo to skip re-renders when its props are unchanged.

Syntaxconst MemoizedList = memo(List);

memo wraps a component so React skips re-rendering it when its props have not changed (by shallow comparison). Use it for components that render often with the same props or that are expensive to render.

Make it effective

  • Ensure props are stable — memoize object/array/function props with useMemo / useCallback.
  • A new object or function prop each render defeats memo.

Example

Example · javascript
import { memo } from 'react';

const ExpensiveList = memo(function ExpensiveList({ items }) {
  return (
    <ul>
      {items.map((item) => <li key={item.id}>{item.name}</li>)}
    </ul>
  );
});

export default ExpensiveList;

When to use it

  • A large data table memoizes each row component so only the rows whose data changed re-render when a single cell is updated, preventing full table repaints.
  • A sidebar navigation wrapped in memo skips re-rendering when the main content area updates state, since the sidebar's props never change during those updates.
  • A chart component is memo-wrapped so frequent polling state updates in the parent do not cause the expensive SVG layout to recalculate on every tick.

More examples

Basic memo usage

Wraps the component in memo so React skips re-rendering it when the parent updates but the task prop is the same.

Example · jsx
import { memo } from 'react';

const TaskRow = memo(function TaskRow({ task }) {
  console.log('Rendering', task.id);
  return <tr><td>{task.title}</td><td>{task.status}</td></tr>;
});

export default TaskRow;

memo with custom comparator

Passes a custom comparison function as the second argument to memo for more precise control over re-render conditions.

Example · jsx
import { memo } from 'react';

const PriceTag = memo(
  function PriceTag({ amount, currency }) {
    return <span>{currency}{amount.toFixed(2)}</span>;
  },
  (prev, next) => (
    prev.amount === next.amount && prev.currency === next.currency
  )
);

export default PriceTag;

memo plus useCallback on parent

Pairs memo on the child with useCallback on the parent so the stable callback reference prevents unnecessary re-renders.

Example · jsx
import { useState, useCallback, memo } from 'react';

const Button = memo(({ onClick, label }) => (
  <button onClick={onClick}>{label}</button>
));

function Toolbar() {
  const [count, setCount] = useState(0);
  const handleSave = useCallback(() => console.log('saved'), []);

  return (
    <>
      <p>Count: {count}</p>
      <button onClick={() => setCount(c => c + 1)}>+</button>
      <Button onClick={handleSave} label="Save" />
    </>
  );
}

Discussion

  • Be the first to comment on this lesson.