useSelector và useDispatch hook trong React-Redux hoạt động như thế nào?
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.
Pitfall 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 shallowEqual từ react-redux làm argument thứ hai (useSelector(selector, shallowEqual)) để so sánh từng property, hoặc dùng createSelector (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ụ pitfall 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.
Xem toàn bộ State Management cùng filter theo level & chủ đề con.