Nếu bạn chỉ nghĩ key là cái props để React đỡ báo lỗi đỏ trong Console khi dùng .map(), bạn đang bỏ lỡ 50% sức mạnh của nó.
Trong React, Key chính là Danh tính (Identity).
1. Cơ chế Reconciliation với Key
Khi một component re-render, React tạo ra một danh sách các "đối tượng mong muốn" (Virtual DOM mới) và so sánh với "thực tế hiện tại" (Real DOM).
React sử dụng 2 thông tin để nhận diện một phần tử:
- Type: Nó là cái gì? (
div,span,MyComponent). - Key: Nó là "thằng nào" trong đám cùng loại?
Nếu type giống nhau nhưng key khác nhau -> React hiểu đây là 2 thực thể khác biệt. Nó sẽ Xóa (Unmount) cái cũ và Tạo mới (Mount) cái mới.
2. Tại sao dùng index làm key lại nguy hiểm?
Hãy tưởng tượng bạn có 1 danh sách 3 phần tử [A, B, C] với key lần lượt là [0, 1, 2].
Nếu bạn xóa A, danh sách còn [B, C]. Lúc này B mang key 0 và C mang key 1.
Hệ quả kinh điển:
- React soi vào key
0(vốn là củaA), thấy giờ làB. Nó tưởngAvừa được cập nhật dữ liệu thànhB. - Nếu
Ađang có một cái input mà user đang gõ dở (Local State), cái input đó vẫn sẽ nằm lại và hiển thị trong hàng củaB. - Đây là nguồn cơn của những bug "ma ám" trong các ứng dụng quản lý bảng biểu phức tạp.
Quy tắc vàng: Key phải là Duy nhất (Unique) và Bền vững (Stable). ID từ database là lựa chọn tốt nhất.
3. Kỹ thuật: Reset Component bằng Key (The Reset Pattern)
Đây là kỹ thuật "Senior" giúp code cực kỳ sạch. Thay vì dùng useEffect để quan sát ID thay đổi và reset state thủ công, hãy dùng key.
// Scenario: Trang chi tiết sản phẩm.
// Khi ID sản phẩm thay đổi, bạn muốn toàn bộ state của UI
// (tab đang chọn, số lượng mua, nội dung comment...) được xóa sạch.
function ProductPage({ productId }) {
return (
<main>
<ProductNavigation />
{/* 🚀 Ngay khi productId đổi, React sẽ hủy toàn bộ Detail component
cũ và mount cái mới sạch sẽ 100% */}
<ProductDetail key={productId} id={productId} />
</main>
);
}4. Key giúp thực thi Animation
Nếu bạn muốn một animation (như hiệu ứng fade-in) chạy lại mỗi khi nội dung thay đổi, hãy bọc nội dung đó bằng một key.
<div key={contentId} className="transition-all duration-500 opacity-100">
{content}
</div>Mỗi lần contentId đổi, div sẽ được mount lại và class CSS animation sẽ kích hoạt từ đầu.
Kết luận
- Key = Danh tính.
- Dùng key để điều khiển việc Mount/Unmount một cách chủ động.
- Tránh dùng
Math.random()làm key vì nó sẽ khiến component bị remount ở MỌI lần render (thảm họa hiệu năng). - Tránh dùng
indexcho danh sách động.
Làm chủ key là bạn đang làm chủ cách React quản lý cây component và trạng thái một cách sâu sắc nhất.