Skip to content

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
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 ​

SettingTypeDefaultDescription
EnabledboolfalseEnable hooks generation. Requires FilePath — Enabled without FilePath fails at startup.
FilePathstringnullOutput 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.
FileOverwritebooltrueOverwrite existing files.
QueryKeyPrefixstringnullLiteral first element of every query key — use it to namespace cache entries when an app consumes multiple NpgsqlRest APIs.
ExposeQueryKeysbooltrueExport query-key factories. When false, key expressions are inlined into the hooks and no factories are exported.
ImportFromstring"@tanstack/react-query"Import specifier for TanStack Query — point it at an internal wrapper module when direct imports are not allowed.
HeaderLinesarray["// 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
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 FilePath values and derive all types from them (Parameters<typeof fn>[0] / Awaited<ReturnType<typeof fn>>) — nothing depends on ExportTypes or CreateSeparateTypeFile.
  • The whole request object is a query-key segment (TanStack v5 hashes keys with stable, key-order-insensitive serialization), so changing the request re-fetches automatically.
  • QueryKeyPrefix becomes the literal first element of every key — use it to namespace cache entries when an app consumes multiple NpgsqlRest APIs.
  • ExposeQueryKeys: false inlines the key expressions into the hooks and exports no factories.
  • No automatic cache invalidation is generated — wire onSuccess through the options passthrough using the exported key factories.
  • The tsclient_hooks=off routine 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 SkipTypes enabled the run logs a warning and skips hooks generation. Enabled without FilePath fails at startup.
  • ImportFrom replaces the @tanstack/react-query import specifier — point it at an internal wrapper module when direct imports are not allowed (the module must re-export useQuery, useMutation, UseQueryOptions and UseMutationOptions with v5 semantics).
  • The generated file assumes the consumer installs @tanstack/react-query v5 (peer dependency); it compiles under tsc --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.

Next Steps ​

Comments