OpenAPI React Query Codegen
npm install @jonaspf/openapi-react-query-codegen> Node.js library that generates React Query (also called TanStack Query) hooks based on an OpenAPI specification file.

- Generates custom react hooks that use React Query's useQuery, useSuspenseQuery, useMutation and useInfiniteQuery hooks
- Generates query keys and functions for query caching
- Generates pure TypeScript clients generated by @hey-api/openapi-ts
```
$ npm install -D @7nohe/openapi-react-query-codegen
Register the command to the scripts property in your package.json file.
`json`
{
"scripts": {
"codegen": "openapi-rq -i ./petstore.yaml -c axios"
}
}
You can also run the command without installing it in your project using the npx command.
`bash`
$ npx --package @7nohe/openapi-react-query-codegen openapi-rq -i ./petstore.yaml -c axios
`
$ openapi-rq --help
Usage: openapi-rq [options]
Generate React Query code based on OpenAPI
Options:
-V, --version output the version number
-i, --input
-o, --output
-c, --client
--request
--format
--lint
--operationId Use operation ID to generate operation names?
--serviceResponse
--base
--enums
--enums
--useDateType Use Date type instead of string for date types for models, this will not convert the data to a Date object
--debug Run in debug mode?
--noSchemas Disable generating JSON schemas
--schemaType
--pageParam
--nextPageParam
--initialPageParam
-h, --help display help for command
`
#### Command
``
$ openapi-rq -i ./petstore.yaml
#### Output directory structure
``
- openapi
- queries
- index.ts <- main file that exports common types, variables, and queries. Does not export suspense or prefetch hooks
- common.ts <- common types
- queries.ts <- generated query hooks
- suspenses.ts <- generated suspense hooks
- prefetch.ts <- generated prefetch hooks learn more about prefetching in in link below
- requests <- output code generated by @hey-api/openapi-ts
#### In your app
##### Using the generated hooks
`tsx
// App.tsx
import { usePetServiceFindPetsByStatus } from "../openapi/queries";
function App() {
const { data } = usePetServiceFindPetsByStatus({ status: ["available"] });
return (
export default App;
`
##### Using the generated typescript client
`tsx
import { useQuery } from "@tanstack/react-query";
import { PetService } from "../openapi/requests/services";
import { usePetServiceFindPetsByStatusKey } from "../openapi/queries";
function App() {
// You can still use the auto-generated query key
const { data } = useQuery({
queryKey: [usePetServiceFindPetsByStatusKey],
queryFn: () => {
// Do something here
return PetService.findPetsByStatus(["available"]);
},
});
return
export default App;
`
##### Using Suspense Hooks
`tsx
// App.tsx
import { useDefaultClientFindPetsSuspense } from "../openapi/queries/suspense";
function ChildComponent() {
const { data } = useDefaultClientFindPetsSuspense({ tags: [], limit: 10 });
return
function ParentComponent() {
return (
<>
>
);
}
function App() {
return (
export default App;
`
##### Using Mutation hooks
`tsx
// App.tsx
import { usePetServiceAddPet } from "../openapi/queries";
function App() {
const { mutate } = usePetServiceAddPet();
const handleAddPet = () => {
mutate({ name: "Fluffy", status: "available" });
};
return (
export default App;
`
##### Invalidating queries after mutation
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.
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.
`tsx
import {
usePetServiceFindPetsByStatus,
usePetServiceAddPet,
UsePetServiceFindPetsByStatusKeyFn,
} from "../openapi/queries";
// App.tsx
function App() {
const [status, setStatus] = React.useState(["available"]);
const { data } = usePetServiceFindPetsByStatus({ status });
const { mutate } = usePetServiceAddPet({
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: [UsePetServiceFindPetsByStatusKeyFn({
status
})],
});
},
});
return (
export default App;
`
##### Using Infinite Query 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:
`yml`
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: 1
Usage of Generated Hooks:
`ts
import { useDefaultServiceFindPaginatedPetsInfinite } from "@/openapi/queries/infiniteQueries";
const { data, fetchNextPage } = useDefaultServiceFindPaginatedPetsInfinite({
limit: 10,
tags: [],
});
`
##### Runtime Configuration
You can modify the default values used by the generated service calls by modifying the OpenAPI configuration singleton object.
It's default location is openapi/requests/core/OpenAPI.ts and it is also exported from openapi/index.ts
Import the constant into your runtime and modify it before setting up the react app.
`typescript
/* main.tsx /
import { OpenAPI as OpenAPIConfig } from './openapi/requests/core/OpenAPI';
...
OpenAPIConfig.BASE = 'www.domain.com/api';
OpenAPIConfig.HEADERS = {
'x-header-1': 'value-1',
'x-header-2': 'value-2',
};
...
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
);
`
`bash`
pnpm install
bash
pnpm test
`$3
`bash
pnpm lint
`$3
`bash
pnpm lint:fix
`$3
`bash
pnpm snapshot
`$3
`bash
npm run build && pnpm --filter @7nohe/react-app generate:api && pnpm --filter @7nohe/react-app test:generated
``MIT