use-q

Command Palette

Search for a command to run...

Practical React Query

use-q is an opinionated way to use TanStack Query — TkDodo's Practical React Query series, encoded as a schema-driven client.

use-q is not a new data-fetching library. It is an opinionated way to use TanStack Query.

The opinions come from Dominik Dorfmeister (TkDodo)'s Practical React Query series: treat the cache as a server-state manager, never hand-write query keys, colocate a query abstraction, invalidate by describing relationships, transform with select, and keep TypeScript inference flowing from the query function.

You still mount a QueryClientProvider. You still pass staleTime, select, and enabled. use-q makes those recommended patterns the path of least resistance so every app doesn't reinvent a query-key factory and a mutation-invalidation graph.

This page is a map, not a restatement of the series. When you want the why behind a default, follow the link to TkDodo. When you want the how in this library, follow the use-q guide next to it.

What use-q bakes in

A query abstraction, not a new mental model

Creating Query Abstractions and The Query Options API argue for a single place that owns queryKey + queryFn (and the types). createApiClient is that place: one schema produces useQ, useM, queryKeys, and the fetcher. React Query API Design — Lessons Learned is the longer argument for co-locating those.

Hierarchical query keys you never type twice

Effective React Query Keys: array keys, coarse-to-fine, plus a factory. use-q keys are always ["api", method, resolvedPath, searchParams]. The client's queryKeys factory is the factory. The query function always receives TanStack's queryFn context (including signal) — you don't thread it yourself. See Query keys.

Automatic invalidation after mutations

Automatic Query Invalidation after Mutations is the problem tags / invalidatesTags solve. You describe which reads depend on which writes in the schema; useM invalidates matching queries in onSettled, as Mastering Mutations recommends — success and error, so rollbacks still refetch the truth. See Tag invalidation.

Transforms and render isolation via select

Don't map in the queryFn. Pass select to useQ — data transformations, render optimizations, and selectors, supercharged.

Types inferred from the schema, not from generics

React Query and TypeScript and Type-safe React Query: let the query function (here: the RouteDefinition) produce the types. You almost never pass generics to useQ / useM.

Errors and status as Query intended them

React Query Error Handling — handle errors where you have the context: globally (onError on the fetcher), per mutation, or with an error boundary (ApiErrorBoundary + useSuspenseQ). Status Checks in React Query still apply: prefer isPending / isError / isSuccess over treating isLoading as the only gate.

Optimistic updates that cancel in-flight queries

useM's optimisticUpdates follow Concurrent Optimistic Updates: cancelQueries, snapshot, setQueryData, rollback on error, invalidate on settle. See Optimistic updates.

Seed the cache; don't copy server state into React state

The cache is the store for server data — React Query as a State Manager, Thinking in React Query, Why You Want React Query. Prefetch and hydrate with useQClient and SSR & loaders (seeding the query cache, placeholder vs initial data, React Query meets React Router). Put a QueryClient in context, not query results — React Query and React Context.

What we don't bake in

The series covers more than a client library should own. use-q leaves these to your app — and to TkDodo:

Two more posts are useful background without being APIs we wrap: Inside React Query (how the observer model works) and React Query — The Bad Parts (query keys and invalidation boilerplate are two of the sharp edges this library exists to blunt). TanStack Router and Query is the Router-specific integration; our SSR & loaders guide shows the shared-cache pattern without duplicating that post.

Feature → post

In use-qRead TkDodo
createApiClient#31 Creating Query Abstractions, #24 The Query Options API
Query keys + queryKeys#8 Effective React Query Keys
tags / invalidatesTags#25 Automatic Query Invalidation after Mutations
useQ select#2 Data Transformations, #30 Selectors, Supercharged
placeholderData / initialData#9 Placeholder and Initial Data
useM + onSettled invalidation#12 Mastering Mutations
Optimistic updates#29 Concurrent Optimistic Updates
useInfiniteQ#26 How Infinite Queries work
ApiErrorBoundary#11 Error Handling
SSR & loaders#16 React Query meets React Router, #17 Seeding the Query Cache

The series index — and every later part — lives on Practical React Query (#1). There is also a React Query FAQs post for the questions that come up after the defaults click.