Deck 5 - Server State + React Query v5 (objective)
Goal: evaluate async data fetching and server-state patterns (cache, retries, invalidation, optimistic updates).
You practice: query keys, enabled/dependent queries, error/loading states, and avoiding redundant local state.
Output style: 1 verdict sentence + 2-3 issues + best fix approach.
Server state vs client state (definition).
React Query: queryKey (why).
Query function contract (baseline).
staleTime (what it controls).
gcTime/cacheTime (what it controls).
isLoading vs isFetching (difference).
enabled (why/when).
Dependent queries (pattern).
Pagination and keepPreviousData (pattern).
Infinite queries (baseline).
Mutations (baseline).
invalidateQueries vs refetchQueries.
setQueryData (when).
Optimistic updates (pattern).
Retry behavior (gotcha).
Error boundaries and suspense (overview).
Prefetching (why).
Abort/cancellation (best practice).
Anti-pattern: useEffect fetch + React Query together.
Gotcha: queryKey missing parameter.
useQuery({
queryKey: ['user'],
queryFn: () => fetch(`/api/users/${id}`).then(r => r.json()),
});Verdict: FAIL
- Issue: queryKey does not include id.
- Impact: cache collisions (wrong user shown).
- Fix: queryKey: [‘user’, id] and validate id.
Gotcha: query runs with undefined id.
useQuery({ queryKey: ['user', id], queryFn: () => fetch(`/api/users/${id}`) });Verdict: FAIL
- Issue: id may be undefined/empty.
- Fix: enabled: !!id and guard in queryFn.
Gotcha: queryKey missing filter/sort.
useQuery({ queryKey: ['items'], queryFn: () => fetch(`/api/items?sort=${sort}`) });Verdict: FAIL
- Issue: inputs not in key (cache collision).
- Fix: include sort/filter in queryKey.
Gotcha: unstable object in queryKey.
useQuery({ queryKey: ['search', { q }], queryFn: ... });Verdict: PARTIAL FAIL
- Issue: object identity can change; refetch churn.
- Fix: use primitives ([‘search’, q]) or stable serialization.