Prompt
Use React Query (@tanstack/react-query) to fetch user data from a mock API. Show a loading indicator while fetching, the user name on success, and an error message on failure.
Solution
React Query's premise is that server state is not client state: data you fetched is a cache of someone else's source of truth — it can be stale, needs refetching, deduplication, and retry — and none of that belongs in useState. The hand-rolled useEffect + useState + isLoading + error fetch has well-known failure modes: race conditions when params change mid-flight, setState after unmount, no caching across screens, every consumer re-implementing retry. useQuery deletes that entire class.
The queryKey is the design center, not a label: ['user', 1] is the cache identity. Two components asking for the same key share one request and one cache entry; changing the key (['user', userId]) automatically refetches; invalidating the key is how mutations trigger refresh. Treat keys as a structured, hierarchical namespace — it's the API you'll build invalidation on.
The three-state render (isLoading / error / data) is exhaustive by construction, and on mobile the defaults quietly do senior work: stale-while-revalidate serves cached data instantly on back-navigation, and refetch-on-reconnect pairs with NetInfo for flaky networks.
Red flag: reaching for useEffect fetching or stuffing server responses into Redux "to have one store." Name the race-condition and staleness problems those create.
Say it: "Server state is a cache, not component state — the query key is the cache identity that drives sharing, refetching, and invalidation, and stale-while-revalidate is what makes mobile back-navigation feel instant."