React so sánh giá trị mới với giá trị hiện tại bằng Object.is và bail out nếu bằng nhau. Nhưng có một chi tiết hay bị hỏi tiếp: React vẫn có thể gọi lại hàm component thêm một lần trước khi quyết định bỏ qua, chỉ là không chạm DOM và không render cây con. Nếu logic render có side effect thì bug sẽ lộ ra ở đây.
Cạm bẫy phổ biến là so sánh tham chiếu, không phải nội dung:
const [user, setUser] = useState({ name: 'An' })
setUser({ name: 'An' }) // object mới → Object.is false → re-render
setUser(user) // cùng tham chiếu → bail out
user.name = 'Binh'; setUser(user) // mutation + cùng tham chiếu → KHÔNG re-render, UI cũDòng cuối là nguyên nhân thường gặp của lỗi "sửa dữ liệu mà giao diện không cập nhật": mutate rồi set lại chính object đó thì React thấy tham chiếu không đổi và bỏ qua. Cách đúng là tạo object mới: setUser({ ...user, name: 'Binh' }).
Mặt tích cực: cơ chế bail out này khiến việc gọi setter với giá trị không đổi (vd đồng bộ từ props hoặc từ sự kiện scroll) trở nên rẻ, nên không cần tự viết if (next !== current) trước mỗi lần set.