← Về danh sách bài họcBài 10/25
🔗 Bài 10: useCallback - Tối Ưu Hàm Callback
🎯 Sau bài học này, bạn sẽ:
- Hiểu tại sao functions mới được tạo mỗi render
- Dùng useCallback kết hợp React.memo hiệu quả
- Phân biệt useMemo vs useCallback
- Tránh các pitfalls phổ biến
1. Vấn Đề: Functions Tạo Mới Mỗi Render
function Parent() {
const [count, setCount] = useState(0);
// ❌ handleClick tạo MỚI mỗi render → Child re-render không cần thiết
const handleClick = () => console.log('clicked');
return (
<div>
<p>{count}</p>
<button onClick={() => setCount(c => c + 1)}>+1</button>
<ExpensiveChild onClick={handleClick} />
</div>
);
}
// React.memo: chỉ re-render khi props thay đổi
const ExpensiveChild = React.memo(({ onClick }) => {
console.log('Child rendered!');
return <button onClick={onClick}>Click me</button>;
});2. useCallback Giải Quyết
import { useCallback, useState, memo } from 'react';
function Parent() {
const [count, setCount] = useState(0);
// ✅ useCallback: giữ cùng reference giữa các render
const handleClick = useCallback(() => {
console.log('clicked');
}, []); // [] = function không bao giờ thay đổi
// Với dependency
const handleAdd = useCallback((item) => {
setItems(prev => [...prev, item]);
}, []); // setItems stable → [] OK
return (
<div>
<p>{count}</p>
<button onClick={() => setCount(c => c + 1)}>+1</button>
<ExpensiveChild onClick={handleClick} /> {/* Không re-render! */}
</div>
);
}
const ExpensiveChild = memo(({ onClick }) => {
console.log('Child rendered!'); // Chỉ log 1 lần
return <button onClick={onClick}>Click me</button>;
});📌 Công thức:
•
•
useCallback(fn, deps) ≡ useMemo(() => fn, deps)•
useMemo ghi nhớ giá trị•
useCallback ghi nhớ function3. Khi Nào Dùng?
✅ NÊN dùng useCallback khi:
• Truyền callback cho component con wrap bởi
• Callback là dependency của
• Component con render nặng (list lớn, chart, canvas)
• Truyền callback cho component con wrap bởi
React.memo• Callback là dependency của
useEffect/useMemo• Component con render nặng (list lớn, chart, canvas)
❌ KHÔNG cần khi:
• Component con không dùng React.memo
• Component render nhẹ, nhanh
• Inline event handler đơn giản
• Component con không dùng React.memo
• Component render nhẹ, nhanh
• Inline event handler đơn giản
📝 Tóm Tắt
useCallback(fn, deps)ghi nhớ reference của function- Kết hợp với
React.memođể ngăn child re-render useCallback=useMemocho functions- Chỉ dùng khi child component thực sự tốn kém để render