select transform data sau fetch trước khi component nhận — cache vẫn lưu raw data; component chỉ re-render khi select result thay đổi; stabilize function với useCallback để tránh re-render không cần thiết. select là transform function chạy sau khi queryFn trả về data, trước khi component nhận — không ảnh hưởng gì đến cache (cache vẫn lưu raw data).
Re-render optimization: React Query memoize select result — component chỉ re-render khi select(data) trả về giá trị khác (dùng structural equality).
Ví dụ: nhiều components dùng cùng query ['todos'] nhưng mỗi component có select khác nhau — select: d => d.filter(t => !t.done) (incomplete) và select: d => d.filter(t => t.done) (complete) — component nào chỉ re-render khi phần data của nó thay đổi.
Patterns thực tế:
- Pick fields:
select: d => ({ name: d.name, avatar: d.avatar })giảm re-render khi các field khác thay đổi. - Sort/filter:
select: d => [...d].sort((a,b) => b.date - a.date). - Normalize:
select: d => Object.fromEntries(d.map(i => [i.id, i]))
Lưu ý: nếu select là inline arrow function, memoization không hoạt động vì function reference thay đổi mỗi render — stabilize bằng useCallback hoặc định nghĩa outside component.
select transforms data after fetch before the component receives it — cache still stores raw data; component only re-renders when the selected result changes; stabilize the function with useCallback to avoid unnecessary re-renders.
- The select option is a transformation function that runs on the fetched data before it is stored in the component's state.
- It does not affect the cached data — only what the component receives.
- Use cases: Data transformation — reshape API response to the format the component needs without modifying the cache; Data filtering — select only a subset of data; Computing derived values — calculate totals, sort lists; Performance optimization — when the select function is memoized, the component only re-renders when the selected data changes (not when other parts of the cache change).
- Best practice: memoize select functions with useCallback or define them as stable references to prevent unnecessary re-renders.
- Example: const { data: userNames } = useQuery({ queryKey: ['users'], queryFn: fetchUsers, select: (data) => data.map(u => u.name) })