When Memoization Backfires

Memoization is never free. Each useMemo or useCallback allocates a dependency array on every render and compares it entry by entry; each memo retains the last props and output while the component is mounted. Against a calculation that takes a microsecond, the bookkeeping costs more than the work. Four patterns lose outright:

Memoization that resets on every renderJavaScript
function Page({ rows }) {
  const Row = memo(({ row }) => <li>{row.title}</li>);   // a NEW component type each render
  return <ul>{rows.map((row) => <Row key={row.id} row={row} />)}</ul>;
}

memo returns a new component object every time Page runs, so React 7,897 sees a different element type, throws away the whole subtree and remounts it — losing its DOM nodes, its state and its Effects along with the cache. Define components at module scope; the only correct place for memo is next to that definition.