Skip to content
Chapter 76Lesson 5

Quiz - TanStack Query

Quiz progress

0 / 0

A teammate wants to add TanStack Query for a “mark as favorite” star that flips instantly and snaps back on a failed request. Run the funnel: does it earn the library, and what owns it instead?

No — it’s one component, one optimistic value, one rollback path, which is exactly useOptimistic. No separate cache is involved, so no library.

Yes — instant-feedback-with-rollback is the optimistic-mutation trigger, which is one of the four reasons to reach for the library.

No — but the right owner is nuqs, since a favorite is shareable view state that should live in the URL.

You set staleTime: 60_000 on a SaaS read instead of leaving the library default of 0. What’s the symptom of the default you’re avoiding, and what still gets fresh data despite the longer stale time?

The default refetches on every mount and tab refocus — a “refetch storm” when the user glances away and back. Polling and explicit invalidateQueries still override staleness, so live data stays fresh.

The default never refetches until the entry is garbage-collected, so data goes permanently stale; raising staleTime is what re-enables background refetches.

The default disables the cache entirely, so every read hits the network; staleTime: 60_000 is what turns caching on in the first place.

Which situations force the cache-update optimistic shape (onMutate + setQueryData) rather than the simpler via-variables shape? Select all that apply.

The pending comment must appear at the top of an infinite thread whose first page already lives in the cache (data.pages[0]).

A second panel on the same screen reads the same query key and must also show the pending comment.

One comment box adds a row inline and removes it on a failed POST, and nothing else on the page reads that list.

A single “Resolve” switch on one row flips instantly and snaps back if the request fails.

In a getNextPageParam, what value signals “there are no more pages,” and why specifically that value?

undefined — because null is a valid first cursor (initialPageParam), so it can’t double as the stop signal; undefined is reserved for “done.”

null — returning null clears the cursor, which the library reads as the end of the list.

falsegetNextPageParam returns a boolean, mirroring hasNextPage.

On your multi-tenant server, one tenant’s comments render inside another tenant’s page. Which line is the cause?

export const queryClient = new QueryClient();
const getServerQueryClient = cache(makeQueryClient);
if (isServer) return getServerQueryClient();

A Server Action posts a comment and calls updateTag(invoiceTag(invoiceId)) internally, but the useInfiniteQuery comment thread stays stale. What’s the fix?

After the action resolves, fire queryClient.invalidateQueries({ queryKey: commentKeys.lists(invoiceId) }) on the client — the TanStack cache is a separate cache that updateTag can’t reach.

Switch the action’s updateTag to revalidateTag(invoiceTag(invoiceId), 'max'), which reaches both the Server Component cache and the TanStack cache.

Add the matching cacheTag to the useInfiniteQuery config so updateTag can find and expire it.

The comment thread clears the bar, so a teammate suggests dropping the Server Action and posting via useMutation + invalidateQueries — “one system, fewer moving parts.” What’s the strongest reason that’s the worse design here?

It throws away the progressive-enhancement form contract, the server-side Zod validation, and the audit-log write the action already owns — work you’d rebuild by hand to dodge an invalidateQueries call you’d make anyway.

useMutation can’t call invalidateQueries, so the thread would never refetch after the post.

A route-handler POST can’t reach the database, so the comment would never persist.

Quiz complete

Score by topic