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' }) // new object → Object.is false → re-render
setUser(user) // same reference → bail out
user.name = 'Binh'; setUser(user) // mutation + same reference → NO re-render, UI staleDòng cuối là nguyên nhân kinh điển 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.