Usage
After generating the React Query hooks and functions, you can start using them in your React application.
Using the generated useQuery hooks
Section titled “Using the generated useQuery hooks”import { useFindPets } from "../openapi/queries";function App() { const { data } = useFindPets();
return ( <div className="App"> <h1>Pet List</h1> <ul>{data?.map((pet) => <li key={pet.id}>{pet.name}</li>)}</ul> </div> );}
export default App;Optionally, you can also use the pure TypeScript client to customize your query. The SDK functions are defined in openapi/requests/sdk.gen.ts and are also available via the backward-compatible openapi/requests/services.gen.ts shim.
import { useQuery } from "@tanstack/react-query";import { findPets } from "../openapi/requests/services.gen";import { useFindPetsKey } from "../openapi/queries";
function App() { // You can still use the auto-generated query key const { data } = useQuery({ queryKey: [useFindPetsKey], queryFn: () => { // Do something here return findPets(); }, });
return <div className="App">{/* .... */}</div>;}
export default App;Using the generated useQuerySuspense hooks
Section titled “Using the generated useQuerySuspense hooks”import { useFindPetsSuspense } from "../openapi/queries/suspense";function ChildComponent() { const { data } = useFindPetsSuspense({ query: { tags: [], limit: 10 }, });
return <ul>{data?.map((pet, index) => <li key={pet.id}>{pet.name}</li>)}</ul>;}
function ParentComponent() { return ( <> <Suspense fallback={<>loading...</>}> <ChildComponent /> </Suspense> </> );}
function App() { return ( <div className="App"> <h1>Pet List</h1> <ParentComponent /> </div> );}
export default App;Using the generated useMutation hooks
Section titled “Using the generated useMutation hooks”import { useAddPet } from "../openapi/queries";
function App() { const { mutate } = useAddPet();
const handleAddPet = () => { mutate({ body: { name: "Fluffy" } }); };
return ( <div className="App"> <h1>Add Pet</h1> <button onClick={handleAddPet}>Add Pet</button> </div> );}
export default App;Generated query functions forward TanStack Query’s AbortSignal to the HTTP
client. Requests are therefore cancelled when a query becomes stale or when
you call queryClient.cancelQueries.
Mutations can be cancelled explicitly by passing a signal in the generated client options:
const controller = new AbortController();const { mutate } = useAddPet();
mutate({ body: { name: "Fluffy" }, signal: controller.signal,});
controller.abort();Invalidating queries after a mutation is important to ensure the cache is updated with the new data. This is done by calling the queryClient.invalidateQueries function with the query key used by the query hook.
Mutation results contain the complete SDK response, not only the response
body. This makes response headers available in onSuccess or from
mutateAsync:
const { mutateAsync } = useDownloadReport();const result = await mutateAsync({ body: { reportId } });
// @hey-api/client-fetchconst disposition = result.response.headers.get("content-disposition");
// @hey-api/client-axiosconst axiosDisposition = result.headers["content-disposition"];Learn more about invalidating queries here.
To ensure the query key is created the same way as the query hook, you can use the query key function exported by the generated query hooks.
import { useFindPetsByStatus, useAddPet, UseFindPetsByStatusKeyFn,} from "../openapi/queries";
function App() { const [status, setStatus] = React.useState(["available"]); const { data } = useFindPetsByStatus({ query: { status } }); const { mutate } = useAddPet({ onSuccess: () => { queryClient.invalidateQueries({ // Call the query key function to get the query key // This is important to ensure the query key is created the same way as the query hook // This insures the cache is invalidated correctly and is typed correctly queryKey: [UseFindPetsByStatusKeyFn({ status })], }); }, });
return ( <div className="App"> <h1>Pet List</h1> <ul>{data?.map((pet) => <li key={pet.id}>{pet.name}</li>)}</ul> <button onClick={() => { mutate({ name: "Fluffy", status: "available" }); }} > Add Pet </button> </div> );}
export default App;Using the generated useInfiniteQuery hooks
Section titled “Using the generated useInfiniteQuery hooks”This feature will generate a function in infiniteQueries.ts when the name specified by the pageParam option exists in the query parameters and the name specified by the nextPageParam option exists in the response.
The initialPageParam option can be specified to set the intial page to load, defaults to 1. The nextPageParam supports dot notation for nested values (i.e. meta.next).
Example Schema:
paths: /paginated-pets: get: description: | Returns paginated pets from the system that the user has access to operationId: findPaginatedPets parameters: - name: page in: query description: page number required: false schema: type: integer format: int32 - name: tags in: query description: tags to filter by required: false style: form schema: type: array items: type: string - name: limit in: query description: maximum number of results to return required: false schema: type: integer format: int32 responses: '200': description: pet response content: application/json: schema: type: object properties: pets: type: array items: $ref: '#/components/schemas/Pet' nextPage: type: integer format: int32 minimum: 1Usage of Generated Hooks:
import { useFindPaginatedPetsInfinite } from "@/openapi/queries/infiniteQueries";
const { data, fetchNextPage } = useFindPaginatedPetsInfinite({ query: { tags: [], limit: 10 }});Using the generated queryOptions factories
Section titled “Using the generated queryOptions factories”Every GET operation also gets a queryOptions factory in queryOptions.ts. The factory bundles the query key and query function into one type-safe object, so you can reuse it with any TanStack Query utility — useQuery, useSuspenseQuery, useQueries, queryClient.prefetchQuery, queryClient.ensureQueryData, queryClient.setQueryData, and more.
import { useQuery, useQueries, useQueryClient } from "@tanstack/react-query";import { findPetsOptions, findPetByIdOptions } from "../openapi/queries";
// Equivalent to the generated useFindPets hook, but composableconst { data } = useQuery(findPetsOptions({ query: { tags: [], limit: 10 } }));
// Fetch multiple queries in parallelconst results = useQueries({ queries: [1, 2, 3].map((id) => findPetByIdOptions({ path: { id } })),});
// Type-safe cache interactionconst queryClient = useQueryClient();const pets = queryClient.getQueryData(findPetsOptions().queryKey);Paginatable operations additionally get an infiniteQueryOptions factory. It uses a dedicated query key (suffixed with Infinite) so cached infinite data never collides with the plain query cache for the same operation.
import { useInfiniteQuery, useQueryClient } from "@tanstack/react-query";import { findPaginatedPetsInfiniteOptions } from "../openapi/queries";
const { data, fetchNextPage } = useInfiniteQuery( findPaginatedPetsInfiniteOptions({ query: { tags: [], limit: 10 } }),);
// Prefetch an infinite query on the server or in a router loaderconst queryClient = useQueryClient();await queryClient.prefetchInfiniteQuery(findPaginatedPetsInfiniteOptions());The factory takes a third argument for the pagination overrides, so a custom scheme can be defined once and reused everywhere the factory is:
const petPages = findPaginatedPetsInfiniteOptions({}, undefined, { initialPageParam: "", getNextPageParam: (lastPage) => lastPage.meta?.cursor,});