← Về danh sách bài họcBài 10/25

🔗 Bài 10: useCallback - Tối Ưu Hàm Callback

⏱️ Thời gian đọc: 12 phút | 📚 Độ khó: Trung bình

🎯 Sau bài học này, bạn sẽ:

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ớ function

3. Khi Nào Dùng?

✅ NÊN dùng useCallback khi:
• 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

📝 Tóm Tắt