Introduction
openapi-react-query is a type-safe tiny wrapper (1 kb) around @tanstack/react-query to work with OpenAPI schema.
It works by using openapi-fetch and openapi-typescript so you get all the following features:
- ✅ No typos in URLs or params.
- ✅ All parameters, request bodies, and responses are type-checked and 100% match your schema
- ✅ No manual typing of your API
- ✅ Eliminates
any
types that hide bugs - ✅ Also eliminates
as
type overrides that can also hide bugs
tsx
import createFetchClient from "openapi-fetch"; import createClient from "openapi-react-query"; import type { paths } from "./my-openapi-3-schema"; // generated by openapi-typescript const fetchClient = createFetchClient<paths>({ baseUrl: "https://myapi.dev/v1/", }); const $api = createClient(fetchClient); const MyComponent = () => { const { data, error, isLoading } = $api.useQuery( "get", "/blogposts/{post_id}", { params: { path: { post_id: 5 }, }, }, ); if (isLoading || !data) return "Loading..."; if (error) return `An error occured: ${error.message}`; return <div>{data.title}</div>; };
Setup
Install this library along with openapi-fetch and openapi-typescript:
bash
npm i openapi-react-query openapi-fetch npm i -D openapi-typescript typescript
Highly recommended
Enable noUncheckedIndexedAccess in your tsconfig.json
(docs)
Next, generate TypeScript types from your OpenAPI schema using openapi-typescript:
bash
npx openapi-typescript ./path/to/api/v1.yaml -o ./src/lib/api/v1.d.ts
Basic usage
Once your types has been generated from your schema, you can create a fetch client, a react-query client and start querying your API.
tsx
import createFetchClient from "openapi-fetch"; import createClient from "openapi-react-query"; import type { paths } from "./my-openapi-3-schema"; // generated by openapi-typescript const fetchClient = createFetchClient<paths>({ baseUrl: "https://myapi.dev/v1/", }); const $api = createClient(fetchClient); const MyComponent = () => { const { data, error, isLoading } = $api.useQuery( "get", "/blogposts/{post_id}", { params: { path: { post_id: 5 }, }, }, ); if (isLoading || !data) return "Loading..."; if (error) return `An error occured: ${error.message}`; return <div>{data.title}</div>; };
TIP
You can find more information about createFetchClient
on the openapi-fetch documentation.