React Query
Officialv5.3.2@kubb/plugin-react-query
Call operations
@kubb/plugin-react-query can generate a typed TanStack Query hook for each operation. GET operations get query hooks such as useGetPetById, and POST, PUT, PATCH, and DELETE operations get mutation hooks such as useDeletePet. Each hook calls the client function from @kubb/plugin-fetch or @kubb/plugin-axios.
queryOptions, mutationOptions, queryKey, mutationKey). Set hooks: true in the plugin options to also generate the use* hooks shown below.Queries
A query hook takes the operation's grouped request config (path, query, headers, whichever the operation declares) as its first argument and returns a TanStack UseQueryResult:
import { useGetPetById } from './gen/hooks/useGetPetById'
const { data, error, isLoading } = useGetPetById({ path: { petId: 1n } })The second argument has two optional groups. query takes any TanStack Query option, and query.client sets the QueryClient to use. The top-level client takes request config for this call, such as baseURL or signal:
import { useGetPetById } from './gen/hooks/useGetPetById'
useGetPetById(
{ path: { petId: 1n } },
{
query: { staleTime: 60_000 },
client: { baseURL: 'https://api.example.com/v1' },
},
)Factories
Each query operation also exports a queryOptions factory and a queryKey helper. Use them to prefetch or invalidate a query outside a hook. The key includes the operation URL and path parameters, followed by query or body values when present:
import { useQueryClient } from '@tanstack/react-query'
import { getPetByIdQueryKey, getPetByIdQueryOptions } from './gen/hooks/useGetPetById'
const queryClient = useQueryClient()
await queryClient.prefetchQuery(getPetByIdQueryOptions({ path: { petId: 1n } }))
queryClient.invalidateQueries({ queryKey: getPetByIdQueryKey({ path: { petId: 1n } }) })Mutations
A mutation hook takes only an options object. The grouped request config is the mutation variable, so you pass it to mutate or mutateAsync:
import { useQueryClient } from '@tanstack/react-query'
import { useDeletePet } from './gen/hooks/useDeletePet'
const queryClient = useQueryClient()
const { mutate } = useDeletePet({
mutation: { onSuccess: () => queryClient.invalidateQueries() },
})
mutate({ path: { petId: 1n } })Each mutation also exports a mutationOptions factory and a mutationKey helper.
Errors and transport
Each generated hook calls the client function with throwOnError: true. A failed request sets TanStack Query's error, typed from the error responses in the spec. Set the base URL, authentication, interceptors, serialization, and validation on the client plugin. See the plugin-fetch or plugin-axios guide.
Customize cache keys
Set queryKey on the plugin to change generated keys. String entries are emitted as source code, so use JSON.stringify for a string literal.
import { pluginReactQuery } from '@kubb/plugin-react-query'
pluginReactQuery({
queryKey: ({ node }) => [JSON.stringify(node.operationId)],
})queryKey gives every call the same key, such as ['getUserByName']. If path or query values select different data, add them to the key.Load more pages
Configure infinite with a query parameter declared by the operation, its initial value, and the response path for the next cursor. Infinite output needs hooks: true, and only operations that declare the queryParam receive it.
import { pluginReactQuery } from '@kubb/plugin-react-query'
pluginReactQuery({
hooks: true,
infinite: {
queryParam: 'page',
initialPageParam: 0,
nextParam: 'pagination.next.cursor',
},
})import { useInfiniteQuery } from '@tanstack/react-query'
import { findPetsByTagsInfiniteQueryOptions } from './gen/hooks/useFindPetsByTagsInfinite'
const { data, fetchNextPage, hasNextPage } = useInfiniteQuery(
findPetsByTagsInfiniteQueryOptions({ query: { tags: ['dog'] } }),
)nextParam takes dot notation or an array of keys. Change it to match your API's response. Without getNextPageParam, nextParam or cursorParam, the generated options increment the page number until a page returns an empty array.
Use suspense
Set suspense: {} and hooks: true to generate suspense hooks alongside regular hooks. Suspense requires TanStack Query v5 or higher.
import { pluginReactQuery } from '@kubb/plugin-react-query'
pluginReactQuery({ hooks: true, suspense: {} })import { useGetPetByIdSuspense } from './gen/hooks/useGetPetByIdSuspense'
const { data } = useGetPetByIdSuspense({ path: { petId: 1n } })Share hook options
Set customOptions to call one options function from every generated hook.
import { pluginReactQuery } from '@kubb/plugin-react-query'
pluginReactQuery({
hooks: true,
customOptions: {
importPath: './useCustomHookOptions',
name: 'useCustomHookOptions',
},
})Create the function at importPath, resolved from the generated hooks folder (here src/gen/hooks/useCustomHookOptions.ts). Each hook passes { hookName, operationId }. The generated barrel re-exports HookOptions.
import type { HookOptions } from './HookOptions'
export function useCustomHookOptions(
{ hookName }: { hookName: keyof HookOptions; operationId: string },
) {
if (hookName === 'useGetPetById') {
return { staleTime: 60_000 } satisfies HookOptions['useGetPetById']
}
return {}
}Per-call query options override shared options.