useSelector nhận selector function, subscribe vào Redux store, và dùng strict === comparison (reference equality) để quyết định có re-render không.
- Lưu ý quan trọng: nếu selector trả về object/array mới mỗi lần gọi — ví dụ
useSelector(s => s.items.filter(...))— reference luôn khác nên component re-render liên tục dù data không đổi. - Fix: dùng
shallowEqualtừ react-redux làm argument thứ hai (useSelector(selector, shallowEqual)) để so sánh từng property, hoặc dùngcreateSelector(Reselect) để memoize. useDispatch trả về stable dispatch reference — không bao giờ thay đổi giữa các render, an toàn khi đặt vào dependency array. - So sánh với connect() HOC cũ: connect() dùng shallowEqual mặc định nên ít gặp re-render issue hơn, nhưng code verbose (mapStateToProps, mapDispatchToProps) và wrap component trong HOC gây khó debug. useSelector/useDispatch code gọn hơn 50% nhưng developer phải tự xử lý equality.
Ví dụ lỗi thực tế: useSelector(s => ({ a: s.a, b: s.b })) tạo object mới mỗi render → infinite re-render loop khi có dispatch trong useEffect — fix bằng 2 useSelector riêng biệt hoặc shallowEqual.