Skip to content

Introduction ​

Fork of openapi-react-query in openapi-ts/openapi-typescript, maintained by Vladimir Iglovikov. Original authorship and MIT license notices are preserved.

@ternaus/openapi-react-query is a typed client for @tanstack/react-query to work with OpenAPI schema.

TypeScript checks request fields and infers response shapes from the types generated by openapi-typescript. The client sends requests through openapi-fetch.

tsx
import createFetchClient from "@ternaus/openapi-fetch";
import createClient from "@ternaus/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 ​

Requires React 19 and TanStack Query 5.

Install this library along with openapi-fetch and openapi-typescript:

bash
npm i @ternaus/openapi-react-query @ternaus/openapi-fetch
npm i -D @ternaus/openapi-typescript typescript

tip Highly recommended

Enable noUncheckedIndexedAccess in your tsconfig.json (docs)

Next, generate TypeScript types from your OpenAPI schema using openapi-typescript:

bash
npx @ternaus/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 "@ternaus/openapi-fetch";
import createClient from "@ternaus/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.

Cache identity and HTTP errors ​

Query keys include the fetch client's normalized baseUrl, an optional cacheKey, the query mode, HTTP method, path, and fetch options. Normal and infinite queries have separate keys. Clients with the same base URL share their cache by default.

For different users or middleware on one server, give each client a stable cache key:

ts
const $api = createClient(fetchClient, {
  cacheKey: "user-123",
});

Use $api.queryOptions(method, path, init).queryKey when reading or invalidating a normal query. Keys from older versions have a different shape; rebuild them when upgrading. Query settings such as retry belong in the fourth argument, after the fetch options.

Unsuccessful HTTP responses reject with their parsed error payload. If the body is empty, they reject with an Error whose message includes the HTTP status and whose cause is the original Response. The public error type includes Error. Empty successful queries return null; successful mutations keep their original data, including undefined for an empty body.

MIT licensed. Original package license notices remain with each package.