Careeroza
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
| Tool | Memoizes | Prevents |
|---|---|---|
| React.memo | a component | re-render when props are equal |
| useMemo | a computed value | re-calculation and new object references |
| useCallback | a function | new function references |
Note: Use them where profiling shows a slow component. The React Compiler (React 19) can add this memoization automatically.