Luôn dùng selector cụ thể trong Zustand — gọi useStore() không có selector subscribe toàn bộ store và re-render khi bất kỳ state nào thay đổi.
Zustand mặc định dùng strict === equality để so sánh — nếu selector trả về primitive (number, string, boolean) thì không vấn đề gì.
Vấn đề xảy ra khi selector trả về object/array mới mỗi lần: useStore(s => ({ a: s.a, b: s.b })) tạo object mới mỗi render → component luôn re-render.
Giải pháp:
- Tách thành 2 selectors riêng:
const a = useStore(s => s.a); const b = useStore(s => s.b). - Dùng
useShallowhook từ 'zustand/react/shallow' để shallow compare object/array:const { a, b } = useStore(useShallow(s => ({ a: s.a, b: s.b }))). - Dùng
createSelectorspattern để auto-generate per-property selectors
Auto-selector pattern: const createSelectors = (store) => { const s = store; s.use = {}; Object.keys(s.getState()).forEach(k => { s.use[k] = () => s(x => x[k]) }); return s } → dùng useStore.use.count().
Pitfall khác: gọi useStore() không truyền selector → subscribe toàn bộ store, re-render khi bất kỳ state nào thay đổi.