Cả hai đều cache một thứ gì đó xuyên qua các lần render để nó không bị tính lại/tạo lại mỗi lần:
useMemocache một .
Cả hai đều cache một thứ gì đó xuyên qua các lần render để nó không bị tính lại/tạo lại mỗi lần:
useMemo cache một .useCallback cache danh tính (identity) của một hàm (nó chính là useMemo(() => fn, deps)).Chúng tồn tại để tránh (a) lặp lại công việc tốn kém và (b) phá vỡ tính bằng nhau theo tham chiếu (referential equality) mà các component con đã được memo hóa dựa vào.
function Table({ rows, onSelect }) {
// (a) phép tính tốn kém — chỉ tính lại khi `rows` thay đổi
const sorted = useMemo(() => rows.slice().sort(byName), [rows]);
// (b) danh tính hàm ổn định — để một component con React.memo không re-render,
// và các effect phụ thuộc vào nó không chạy lại
const handleSelect = useCallback(id => onSelect(id), [onSelect]);
return <Grid rows={sorted} onSelect={handleSelect} />;
}
Nếu không có useCallback, handleSelect là một hàm hoàn toàn mới ở mỗi lần render. Một React.memo(Grid) sẽ thấy một prop "mới" và vẫn re-render, làm vô hiệu việc memo hóa. Tương tự với một object truyền vào component con đã memo hóa hoặc được dùng trong mảng dependency của một useEffect.
const x = useMemo(() => a + b, [a, b]); // ❌ vô nghĩa — phép cộng còn rẻ hơn việc memo hóa
useMemo/useCallback ở khắp nơi một cách vội vàng làm tăng nhiễu và thậm chí có thể chậm hơn. (Compiler của React 19 có thể tự động memo hóa, giảm bớt nhu cầu này.)