Skip to main content
TanStack Query plugins generate fully typed query options, mutation options, query keys, and optional hooks for your OpenAPI operations. Support is available for React, Vue, Svelte, Solid, and Angular.

Available Plugins

React Query

@tanstack/react-query

Vue Query

@tanstack/vue-query

Svelte Query

@tanstack/svelte-query

Solid Query

@tanstack/solid-query

Angular Query

@tanstack/angular-query-experimental

Installation

1

Install Dependencies

Install your framework’s TanStack Query package:
npm install @tanstack/react-query
2

Configure Plugin

Add the plugin to your openapi-ts.config.ts:
import { defineConfig } from '@hey-api/openapi-ts';

export default defineConfig({
  input: 'https://api.example.com/openapi.json',
  output: {
    path: './src/client',
  },
  plugins: [
    '@hey-api/client-fetch',
    '@hey-api/sdk',
    '@hey-api/typescript',
    '@tanstack/react-query',
  ],
});
3

Generate Client

Run the generator:
npx @hey-api/openapi-ts

Generated Code

The plugin generates the following artifacts for each operation:

Query Options (GET operations)

For GET operations, query options are generated with the naming pattern {{name}}Options (default):
packages/openapi-ts/src/plugins/@tanstack/query-core/v5/queryOptions.ts
export const findPetsByStatusOptions = (options: Options<FindPetsByStatusData>) =>
  queryOptions<
    FindPetsByStatusResponse,
    DefaultError,
    FindPetsByStatusResponse,
    ReturnType<typeof findPetsByStatusQueryKey>
  >({
    queryFn: async ({ queryKey, signal }) => {
      const { data } = await client.findPetsByStatus({
        ...options,
        ...queryKey[0],
        signal,
        throwOnError: true,
      });
      return data;
    },
    queryKey: findPetsByStatusQueryKey(options),
  });

Mutation Options (POST/PUT/DELETE operations)

For mutations, mutation options are generated with the naming pattern {{name}}Mutation (default):
packages/openapi-ts/src/plugins/@tanstack/query-core/v5/mutationOptions.ts
export const addPetMutation = (
  options?: Partial<Options<AddPetData>>,
): UseMutationOptions<AddPetResponse, DefaultError, Options<AddPetData>> => {
  const mutationOptions: UseMutationOptions<AddPetResponse, DefaultError, Options<AddPetData>> = {
    mutationFn: async (fnOptions) => {
      const { data } = await client.addPet({
        ...options,
        ...fnOptions,
        throwOnError: true,
      });
      return data;
    },
  };
  return mutationOptions;
};

Query Keys

Query key functions are generated with the naming pattern {{name}}QueryKey (default):
export const getPetByIdQueryKey = (options: Options<GetPetByIdData>) =>
  createQueryKey('getPetById', options);

Infinite Query Options

For paginated operations (detected via pagination parameters), infinite query options are generated:
packages/openapi-ts/src/plugins/@tanstack/query-core/v5/infiniteQueryOptions.ts
export const findPetsByStatusInfiniteOptions = (options: Options<FindPetsByStatusData>) =>
  infiniteQueryOptions({
    queryFn: async ({ pageParam, queryKey, signal }) => {
      const page = typeof pageParam === 'object'
        ? pageParam
        : { query: { offset: pageParam } };
      const params = createInfiniteParams(queryKey, page);
      const { data } = await client.findPetsByStatus({
        ...options,
        ...params,
        signal,
        throwOnError: true,
      });
      return data;
    },
    queryKey: findPetsByStatusInfiniteQueryKey(options),
  });

Configuration

All TanStack Query plugins support the same configuration options:

Query Options

Configure query options generation:
export default defineConfig({
  plugins: [
    {
      name: '@tanstack/react-query',
      queryOptions: {
        // Naming pattern (default: '{{name}}Options')
        name: '{{name}}QueryOptions',
        // Enable/disable generation (default: true)
        enabled: true,
        // Export from generated file (default: true)
        exported: true,
        // Add custom metadata
        meta: (operation) => ({
          operationId: operation.id,
          tags: operation.tags,
        }),
      },
    },
  ],
});

Mutation Options

Configure mutation options generation:
export default defineConfig({
  plugins: [
    {
      name: '@tanstack/react-query',
      mutationOptions: {
        // Naming pattern (default: '{{name}}Mutation')
        name: '{{name}}MutationOptions',
        // Enable/disable generation (default: true)
        enabled: true,
        // Add custom metadata
        meta: (operation) => ({
          invalidatesTags: operation.tags,
        }),
      },
    },
  ],
});

Query Keys

Configure query key generation:
export default defineConfig({
  plugins: [
    {
      name: '@tanstack/react-query',
      queryKeys: {
        // Naming pattern (default: '{{name}}QueryKey')
        name: '{{name}}Key',
        // Enable/disable generation (default: true)
        enabled: true,
        // Include operation tags in keys for better cache invalidation
        tags: true,
      },
    },
  ],
});

Infinite Query Options

Configure infinite query options:
export default defineConfig({
  plugins: [
    {
      name: '@tanstack/react-query',
      infiniteQueryOptions: {
        // Naming pattern (default: '{{name}}InfiniteOptions')
        name: '{{name}}InfiniteQueryOptions',
        // Enable/disable generation (default: true)
        enabled: true,
      },
      infiniteQueryKeys: {
        // Naming pattern (default: '{{name}}InfiniteQueryKey')
        name: '{{name}}InfiniteKey',
        // Enable/disable generation (default: true)
        enabled: true,
        // Include tags in infinite query keys
        tags: false,
      },
    },
  ],
});

useQuery Hooks (React only)

Optionally generate useQuery hooks that wrap query options:
export default defineConfig({
  plugins: [
    {
      name: '@tanstack/react-query',
      useQuery: {
        // Naming pattern (default: 'use{{name}}Query')
        name: 'use{{name}}',
        // Enable/disable generation (default: false)
        enabled: true,
      },
    },
  ],
});
This generates hooks like:
packages/openapi-ts/src/plugins/@tanstack/query-core/v5/useQuery.ts
export const useGetPetByIdQuery = (options: Options<GetPetByIdData>) =>
  useQuery(getPetByIdOptions(options));

Usage Examples

Basic Query

import { useQuery } from '@tanstack/react-query';
import { getPetByIdOptions } from './client/@tanstack/react-query.gen';

function PetDetails({ petId }: { petId: number }) {
  const { data, error, isLoading } = useQuery(
    getPetByIdOptions({
      path: { petId },
    })
  );

  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;
  return <div>{data.name}</div>;
}

Mutations

import { useMutation, useQueryClient } from '@tanstack/react-query';
import { addPetMutation, getPetByIdQueryKey } from './client/@tanstack/react-query.gen';

function AddPetForm() {
  const queryClient = useQueryClient();
  const mutation = useMutation({
    ...addPetMutation(),
    onSuccess: (data) => {
      // Invalidate related queries
      queryClient.invalidateQueries({
        queryKey: getPetByIdQueryKey({ path: { petId: data.id } }),
      });
    },
  });

  const handleSubmit = async (formData: FormData) => {
    await mutation.mutateAsync({
      body: {
        name: formData.get('name') as string,
        status: 'available',
      },
    });
  };

  return <form onSubmit={handleSubmit}>{/* form fields */}</form>;
}

Infinite Queries

examples/openapi-ts-tanstack-react-query/src/App.tsx
import { useInfiniteQuery } from '@tanstack/react-query';
import { findPetsByStatusInfiniteOptions } from './client/@tanstack/react-query.gen';

function PetList() {
  const { data, fetchNextPage, hasNextPage, isLoading } = useInfiniteQuery({
    ...findPetsByStatusInfiniteOptions({
      query: { status: 'available' },
    }),
    initialPageParam: 0,
    getNextPageParam: (lastPage, pages) => {
      return lastPage.length === 20 ? pages.length * 20 : undefined;
    },
  });

  return (
    <div>
      {data?.pages.map((page) =>
        page.map((pet) => <div key={pet.id}>{pet.name}</div>)
      )}
      {hasNextPage && (
        <button onClick={() => fetchNextPage()}>Load More</button>
      )}
    </div>
  );
}

With Custom Client

Pass a custom client instance to generated options:
import { createClient } from './client/client';
import { getPetByIdOptions } from './client/@tanstack/react-query.gen';

const customClient = createClient({
  baseUrl: 'https://api.example.com',
  headers: {
    Authorization: 'Bearer token',
  },
});

const { data } = useQuery(
  getPetByIdOptions({
    client: customClient,
    path: { petId: 1 },
  })
);

Query Key Structure

Generated query keys follow this structure:
type QueryKey<TOptions extends Options> = [
  Pick<TOptions, 'baseUrl' | 'body' | 'headers' | 'path' | 'query'> & {
    _id: string;           // Operation ID
    _infinite?: boolean;   // True for infinite queries
    tags?: string[];       // Operation tags (if enabled)
  },
];
Example:
const key = getPetByIdQueryKey({ path: { petId: 1 } });
// [
//   {
//     _id: 'getPetById',
//     baseUrl: 'https://api.example.com',
//     path: { petId: 1 },
//   }
// ]

Advanced Patterns

Global Configuration

Apply configuration across all operations:
export default defineConfig({
  plugins: [
    {
      name: '@tanstack/react-query',
      // Apply to all operations
      case: 'camelCase',
      comments: true,
      // Add tags to all query keys
      queryKeys: {
        tags: true,
      },
      // Add metadata to all queries
      queryOptions: {
        meta: (operation) => ({
          operationId: operation.id,
          method: operation.method,
          path: operation.path,
        }),
      },
    },
  ],
});

Selective Feature Generation

export default defineConfig({
  plugins: [
    {
      name: '@tanstack/react-query',
      // Only generate query options and keys
      queryOptions: true,
      queryKeys: true,
      // Disable mutations and infinite queries
      mutationOptions: false,
      infiniteQueryOptions: false,
    },
  ],
});

TanStack Query Docs

Official TanStack Query documentation

SDK Plugin

Learn about the SDK plugin used by TanStack Query

Client Plugins

Configure HTTP clients (Fetch, Axios, etc.)

State Management Overview

Overview of all state management options

Build docs developers (and LLMs) love