TanStack Query (React Query) Hooks
Available since version 3.20.0. The TypeScript client generator can emit a TanStack Query v5 hooks module alongside each generated client module: useQuery hooks for GET endpoints and useMutation hooks for everything else.
Overview
json
{
"NpgsqlRest": {
"ClientCodeGen": {
"ReactQuery": {
"Enabled": false,
"FilePath": null,
"FileOverwrite": true,
"QueryKeyPrefix": null,
"ExposeQueryKeys": true,
"ImportFrom": "@tanstack/react-query",
"HeaderLines": ["// autogenerated at {0}", ""]
}
}
}
}The ReactQuery section is nested inside ClientCodeGen — hooks are generated from the TypeScript client, so the client generator must be enabled too.
Settings
| Setting | Type | Default | Description |
|---|---|---|---|
Enabled | bool | false | Enable hooks generation. Requires FilePath — Enabled without FilePath fails at startup. |
FilePath | string | null | Output path for the hooks module. In multi-file mode — BySchema or tsclient_module usage — it must contain {0}, mirroring the FilePath rules of the client generator. |
FileOverwrite | bool | true | Overwrite existing files. |
QueryKeyPrefix | string | null | Literal first element of every query key — use it to namespace cache entries when an app consumes multiple NpgsqlRest APIs. |
ExposeQueryKeys | bool | true | Export query-key factories. When false, key expressions are inlined into the hooks and no factories are exported. |
ImportFrom | string | "@tanstack/react-query" | Import specifier for TanStack Query — point it at an internal wrapper module when direct imports are not allowed. |
HeaderLines | array | ["// autogenerated at {0}", ""] | Header lines for the generated file. {0} = timestamp. |
Generated Output
Set Enabled to true and point FilePath at the hooks output. Example output for a GET endpoint:
typescript
export const searchTodosKeys = {
all: ["searchTodos"] as const,
byRequest: (request: SearchTodosRequest) =>
["searchTodos", request] as const,
};
export function useSearchTodos(
request: SearchTodosRequest,
options?: Omit<UseQueryOptions<SearchTodosResult>, "queryKey" | "queryFn">,
) {
return useQuery({
queryKey: searchTodosKeys.byRequest(request),
queryFn: () => api.searchTodos(request),
...options,
});
}Non-GET endpoints get use{Name}Mutation(options?) with an Omit<UseMutationOptions<Result, unknown, Request>, "mutationFn"> passthrough and no key factory.
Details
- The hooks import the client functions via a relative import computed from the two
FilePathvalues and derive all types from them (Parameters<typeof fn>[0]/Awaited<ReturnType<typeof fn>>) — nothing depends onExportTypesorCreateSeparateTypeFile. - The whole
requestobject is a query-key segment (TanStack v5 hashes keys with stable, key-order-insensitive serialization), so changing the request re-fetches automatically. QueryKeyPrefixbecomes the literal first element of every key — use it to namespace cache entries when an app consumes multiple NpgsqlRest APIs.ExposeQueryKeys: falseinlines the key expressions into the hooks and exports no factories.- No automatic cache invalidation is generated — wire
onSuccessthrough the options passthrough using the exported key factories. - The
tsclient_hooks=offroutine annotation excludes an endpoint from the hooks file only; the client function is still generated. SSE, upload and url-only endpoints never produce hooks. - Hooks output is TypeScript-only: with
SkipTypesenabled the run logs a warning and skips hooks generation.EnabledwithoutFilePathfails at startup. ImportFromreplaces the@tanstack/react-queryimport specifier — point it at an internal wrapper module when direct imports are not allowed (the module must re-exportuseQuery,useMutation,UseQueryOptionsandUseMutationOptionswith v5 semantics).- The generated file assumes the consumer installs
@tanstack/react-queryv5 (peer dependency); it compiles undertsc --strict.
Example
Example 23 in the examples repository shows the full setup: hooks with key factories and QueryKeyPrefix, a tsclient_hooks=off opt-out, and a consumer component with explicit cache invalidation through the exported key factories.
For the story behind the feature, see the 3.20.0 release post.
Related
- Code Generation - The TypeScript client generator these hooks are built on
- TSCLIENT annotation - Per-endpoint control, including
tsclient_hooks=off - Comment Annotations Guide - How annotations work
Next Steps
- Dart Code Generation - Generate Dart client modules for Flutter projects
- Watch Mode - Regenerate clients and hooks on every schema change
- NpgsqlRest Options - Configure general NpgsqlRest settings