React.memo + useMemo + useCallback

Why memo Alone Is Not Enough

Objects, arrays and functions created during render are new references every time, so React.memo sees "changed" props. Keep them stable with useMemo and useCallback.

Example

Type in the input: the table does not re-render, because rows and onSelect keep the same reference. Change the sort and it does.

import { useState, useMemo, useCallback, memo } from 'react';

const Table = memo(function Table({ rows, onSelect }) {
  console.log('Table render');
  return <ul>{rows.map((r) => <li key={r.id} onClick={() => onSelect(r)}>{r.name} — {r.price}</li>)}</ul>;
});

const data = [{ id: 1, name: 'Pen', price: 10 }, { id: 2, name: 'Book', price: 250 }, { id: 3, name: 'Bag', price: 900 }];

export default function App() {
  const [text, setText] = useState('');
  const [desc, setDesc] = useState(false);

  const rows = useMemo(() => [...data].sort((a, b) => (desc ? b.price - a.price : a.price - b.price)), [desc]);
  const onSelect = useCallback((r) => alert(r.name), []);

  return (
    <div>
      <input value={text} onChange={(e) => setText(e.target.value)} placeholder="Unrelated input" />
      <button onClick={() => setDesc(!desc)}>Sort {desc ? '↑' : '↓'}</button>
      <Table rows={rows} onSelect={onSelect} />
    </div>
  );
}

Result

Summary

ToolMemoizesPrevents
React.memoa componentre-render when props are equal
useMemoa computed valuere-calculation and new object references
useCallbacka functionnew function references

Note: Use them where profiling shows a slow component. The React Compiler (React 19) can add this memoization automatically.