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 useQdata 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.