はじめに
OpenAPIスキーマからReact Query(TanStack Query)のカスタムHooksコードを自動生成できるライブラリを作ってみたので紹介します。
React Query(TanStack Query) はAPIリクエストが多く発生するアプリケーションでの状態管理にはとても便利なライブラリです。 例えば書き方としては以下のようになります。
import { useQuery } from '@tanstack/react-query'
import { getTodos } from '../my-api'
function Todos() {
// Queries
const query = useQuery(['todos'], getTodos)
return (
<div>
// something
</div>
)
}
上記のようにAPIリクエスト関数のimportとtodos
のようなQuery Keyの設定を毎回する必要があり少々面倒です。
そこでOpenAPI Typescript CodegenでTSクライアント生成時と一緒に自動で生成されたTSクライアントからのAPIリクエスト関数とQuery Keyが設定されたカスタムHooksコードを生成できないかと考えこのライブラリを作りました。
このライブラリで生成したHooksを使うと先ほどのコードが以下のようになります。
import { useTodoServiceGetTodos } from "../openapi/queries";
function Todos() {
// Queries
const query = useTodoServiceGetTodos()
return (
<div>
// something
</div>
)
}
地味ですがimport文が一つなくなり、文字列で書いていたQuery Keyが自動で設定されます。
特徴
このライブラリの特徴としては以下です。
- OpenAPIスキーマからReact Query(TanStack Query)のカスタムHooksコードを自動生成できる
- OpenAPI Typescript CodegenのTSコードも一緒に生成されるので、必要に応じてReact Queryを使わない書き方もできる
インストール
$ npm install -D @7nohe/openapi-react-query-codegen
使い方
コード生成
openapi-rq
コマンドを使ってコードを生成します。
例えばpetstore.yamlというOpenAPIスキーマファイルがあったとします。
$ openapi-rq -p ./petstore.yaml
生成されたコードの構成
デフォルトではopenapi
というフォルダが作られそこにqueries
とrequests
が作られます。
queries
はReact QueryのカスタムHooksが置かれ、requests
にはOpenAPI TypeScript Codegenで生成されたファイルが置かれます。
- openapi
- queries
- index.ts <- custom react hooks
- requests <- output code generated by OpenAPI TypeScript Codegen
生成されたコードの例
例えば以下のようなスキーマファイルだったとします。
.
.
paths:
/pets:
get:
description: Returns all pets
operationId: findPets
parameters:
- 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: array
items:
$ref: '#/components/schemas/Pet'
default:
description: unexpected error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
生成されるコードは以下のようになります。
import { useQuery, UseQueryOptions } from "@tanstack/react-query";
import { DefaultClient } from "../requests/services/DefaultClient";
export const useDefaultClientFindPets = ({ tags, limit }: {
tags: Array<string>;
limit: number;
}, queryKey: string[] = [], options?: Omit<UseQueryOptions<Awaited<ReturnType<typeof DefaultClient.findPets>>, unknown, Awaited<ReturnType<typeof DefaultClient.findPets>>, string[]>, "queryKey" | "queryFn" | "initialData">) => useQuery(["DefaultClientFindPets", ...queryKey], () => DefaultClient.findPets(tags, limit), options);
生成したコードの使用例
生成したコードはReactアプリ内で以下のように使えます。
import {
usePetServiceFindPetsByStatus,
} from "../openapi/queries";
function App() {
const { data } = usePetServiceFindPetsByStatus({ status: ["available"] });
return (
<div className="App">
<h1>Pet List</h1>
<ul>
{data?.map((pet) => (
<li key={pet.id}>{pet.name}</li>
))}
</ul>
</div>
);
}
export default App;
このようにAPIリクエスト処理を少ないコード量で書くこともでき、React Queryでの状態管理も行うことができます。
また、カスタマイズしたいときもOpenAPI TypeScript Codegenで生成されたコードをそのまま使ってもOKです。
import { useQuery } from "@tanstack/react-query";
import { PetService } from '../openapi/requests/services/PetService';
function App() {
const { data } = useQuery(['MyKey'], () => {
// Do something here
return PetService.findPetsByStatus(['available']);
});
return (
<div className="App">
{/* .... */}
</div>
);
}
export default App;
おわりに
いかがでしょうか?OpenAPIスキーマからそのまま使えるReact Queryコードが生成されるのは結構良いんじゃないかなと思っています。 今後はテストなどで使えるモックレスポンスを返すHooksコードも一緒に生成できればなと考えています。 気になった方は是非使ってみてください。