火曜日, 4月 29, 2025
ホームニューステックニュース【Next.js + Orval + MSW】型安全 API クライアント & モック環境構築

【Next.js + Orval + MSW】型安全 API クライアント & モック環境構築


こんにちは。チームラボのフロントエンド班の志田です。好きなものはモアイです🗿

今回初めて技術記事を書いてみました。
Next.js、Orval、MSW に関して気になっている方、ちょっと長いですが、ぜひ最後までお付き合いください!

はじめに

フロントエンド開発において、RESTful API を呼び出す処理(API クライアントコード)を作るのは結構手間がかかります。GET なのか POST なのか、リクエストやレスポンスの型は何なのかなど、考慮することが多いです。
といったことから近年では OpenAPI スキーマから、型定義や API クライアントコードを自動で生成するツールがよく使われています。

Orval は、OpenAPI のスキーマから、型安全な API クライアントコードを自動で生成してくれるツールです。
さらには、MSW で利用可能な API モック関数をスキーマから同時に生成することも可能です。

この記事では、Next.js(App Router)プロジェクトに OrvalMSW を導入し、効率的で型安全な API 連携とモック環境を構築する具体的な手順を説明していきます。

対象読者

この記事は、以下のような方を主な対象としています。

  • Next.js(特に App Router)と TypeScript を用いたフロントエンド開発を行なっている方
  • API モックの導入・運用方法を探している方
  • Orval や MSW の導入を検討していて、基本的な使い方を知りたい方

本記事の主な環境

本記事で紹介する手順で使用する主要なものは、以下の環境で動作確認しています。

使用環境

- node: 23.9.0
- npm: 11.1.0
- next: 15.3.1,
- react: 19.0.0,
- @tanstack/react-query: 5.74.4,
- msw: 2.7.5,
- orval: 7.8.0,

なぜ Orval なのか

Orval については、公式ドキュメントや以下の記事で詳しく解説されています。

https://orval.dev/

https://zenn.dev/hrbrain/articles/3ca5d37dd0b80e

その上で自分が Orval を使用する理由としては以下です。

  • JavaScript 環境で HTTP リクエストを送るための fetch、Axios に両方対応している
  • MSW 向けのモックハンドラーおよびモックデータも自動生成可能
  • TanStack Query を使ったカスタムフックが自動生成可能
  • 生成されるコードも比較的シンプルで無駄が少なく、カスタマイズもしやすい

また Orval 以外の API クライアントコード生成ツールとしては以下のようなものがあります。

ご自身の用途に合わせてツールを選ぶのが良いですが、Orval は設定ファイル(後述)によるカスタマイズが豊富なため、近年のフロントエンド技術ではほとんどのケースで問題なく使えるのかなと思います。

Orval の導入

この章から実際に Next.js(App Router)プロジェクトに Orval を導入し、設定していく手順を説明していきます。

1. OpenAPI スキーマファイルの用意

まず最初に、API の設計図となる OpenAPI スキーマファイルが必要です。
実際の開発で使用するものでも良いですし、無い場合は Swagger 公式のサンプルや、AI に生成させるのも良いでしょう。
ファイル形式は yaml または json のどちらでも構いません。
ここでは例として、プロジェクトルートに schemas フォルダを作成し、その中に openapi.yaml という名前で配置するものとします。

  my-next-app/
  ├─ app/
  ├─ schemas/
+ │     └─ openapi.yaml
  ├─ next.config.js
  ├─ package.json
  └─ tsconfig.json
今回使用する openapi.yaml サンプル(色を返すGETメソッド一つのみの、シンプルなAPI)

schemas/openapi.yaml

openapi: 3.0.0
info:
  title: Colors API
  description: 色API
  version: 1.0.0
servers:
  - url: http://localhost:7777


components:
  schemas:
    
    ColorListResponse:
      description: 色の文字列の配列
      type: array
      items:
        type: string
      example: ["red", "green", "blue"] 

    
    ErrorResponse:
      description: 標準的なエラーレスポンス
      type: object
      properties:
        message:
          type: string
          description: エラーの詳細メッセージ
      required: 
        - message
      example: 
        message: Internal Server Error

paths:
  /api/colors:
    get:
      summary: 色の一覧を返す
      description: 色を含む配列を取得します
      operationId: getApiColors 
      tags: 
        - Colors
      responses:
        
        "200":
          description: 色の配列(成功)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ColorListResponse" 

        
        "500":
          description: サーバーエラー
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse" 

またスキーマファイルの中身は OpenAPI v3 の仕様に沿って記述されている必要があります。

2. Orval のインストール

次に、Orval をインストールします。(本記事では以降 npm を使います)

$ npm install orval --save-dev

3. 設定ファイル(orval.config.ts)の作成と基本設定

Orval の動作は設定ファイルによって制御します。プロジェクトルートに orval.config.ts を作成します。

  my-next-app/
  ├─ app/
  ├─ schemas/
  │     └─ openapi.yaml
+ ├─ orval.config.ts
  ├─ next.config.js
  ├─ package.json
  └─ tsconfig.json

orval.config.ts はかなりカスタマイズ可能です。(より詳細は公式 Doc
基本的な設定として、入力となるスキーマファイルの場所と、生成されるコードの出力先を指定することで、とりあえず生成するだけなら以下のような記述だけでも利用可能です。

orval.config.ts

import { defineConfig } from "orval";

export default defineConfig({
  
  color_api: {
    input: "./schemas/openapi.yaml", 
    output: "./apiClient/colors", 
  },
});

ですが実際これで使うのは Orval を使いこなせてなくもったいないので、もうすこし肉付けしましょう。以下今回使用するサンプルです。

orval.config.ts

import { defineConfig } from "orval";

export default defineConfig({
  
  color_api: {
    input: {
      target: "./schemas/openapi.yaml", 
    },
    output: {
      target: "./apiClient/colors", 
      schemas: "./apiClient/schemas", 
      client: "react-query", 
      httpClient: "fetch", 
      mode: "split", 
      clean: true, 
      
      mock: {
        type: "msw",
        useExamples: true, 
      },
      override: {
        mutator: {
          path: "./apiClient/customFetch.ts", 
          name: "customFetch",
        },
        fetch: {
          includeHttpResponseReturnType: false, 
        },
        mock: {
          required: true, 
        },
      },
    },
    hooks: {
      
      
      afterAllFilesWrite: "npx @biomejs/biome format --write", 
    },
  },
});
  • output.client: クライアントコンポーネントでは TanStack Query を活用したいため react-query を指定しています。
  • output.httpClient: 使用環境が Next.js App Router なので、Data Cache を最大限扱うためにも fetch を使用します。
  • output.mode: yaml ファイルのサイズが大きい場合 tags-split をお勧めしますが、今回はサンプルの openapi.yaml 自体が小さいため split にしています。
  • output.override.mutator: 設定しないとただの fetch で処理をすることになるので基本的には custom の fetch 関数をつくり、ここで設定することをお勧めします(後述)
  • hooks.afterAllFilesWrite: 今回コピペで動かすのを想定して npx コマンドの biome にしてますが、prettier などローカルで使用しているものでフォーマットすることをお勧めします。

custom instance(customFetch.ts)の作成

API リクエストに共通のヘッダー(認証トークンなど)を付与したり、ベース URL を一元管理したりするために、先ほどの orval.config.tsoutput.override.mutator に指定した customFetch.ts ファイルを作成します。

  my-next-app/
+ ├─ apiClient/
+ │     └─ customFetch.ts
  ├─ app/
  ├─ schemas/
  │     └─ openapi.yaml
  ├─ orval.config.ts
  ├─ next.config.js
  ├─ package.json
  └─ tsconfig.json

apiClient/customFetch.ts

export const customFetch = async TData>(
  url: string,
  options: RequestInit = {}
): PromiseTData> => {
  const baseUrl = "http://localhost:7777"; 
  const requestUrl = new URL(url, baseUrl);

  const headers = {
    "Content-Type": "application/json", 
    ...options.headers,
    
    
  };

  try {
    const response = await fetch(requestUrl, {
      ...options,
      headers,
    });

    
    if (!response.ok) {
      throw new Error(
        `API request failed with status ${response.status}: ${response.statusText}`
      );
    }

    
    const data: TData = await response.json();
    return data;
  } catch (error) {
    console.error("customFetch Error:", error);
    throw error;
  }
};

今回はできるだけシンプルにしましたが、各自必要に応じて baseUrl 、共通処理やエラーハンドリング処理等を追加してください。
公式にもサンプルがあるので確認するのが良いでしょう。(今回はこちらのサンプルを参考にしています。)

4. コード生成スクリプトの実行

orval.config.ts が準備できたら、コード生成を実行します。
package.json の “scripts” に Orval を実行するコマンドを追加し、コマンドを実行しましょう

package.json

{
  "scripts": {
    ...
    "generate:api": "orval --config ./orval.config.ts"
  }
}

実行に成功すると、今回の設定(orval.config.ts)の場合、以下のようなファイルが生成されていることがわかります。

  my-next-app/
  ├─ apiClient/
+ │     ├─ colors/
+ │     │     ├─ colorsAPI.msw.ts
+ │     │     └─ colorsAPI.ts
+ │     ├─ schemas
+ │     │     ├─ colorListResponse.ts
+ │     │     ├─ errorResponse.ts
+ │     │     └─ index.ts
  │     └─ customFetch.ts
  ├─ app/
  ├─ schemas/
  │     └─ openapi.yaml
  ├─ orval.config.ts
  ├─ next.config.js
  ├─ package.json
  └─ tsconfig.json

実際に生成されたファイルを確認してみる

今回の設定(orval.config.ts)では、colorsAPI.ts にAPIクライアントとなるコードが生成されています。

生成された colorsAPI.ts(一部抜粋)

apiClient/colors/colorsAPI.ts(一部抜粋)

...省略

export const getGetApiColorsUrl = () => {
  return `/api/colors`;
};

export const getApiColors = async (
  options?: RequestInit
): PromiseColorListResponse> => {
  return customFetchColorListResponse>(getGetApiColorsUrl(), {
    ...options,
    method: "GET",
  });
};
...省略

API レスポンスとなる型や fetch を行う getApiColors の中で先ほど設定した customFetch が呼ばれているのがわかりますね。

また使用される型も以下のようにしっかり生成されています。

生成されたレスポンス型ファイル

apiClient/schemas/colorListResponse.ts


export type ColorListResponse = string[];

apiClient/schemas/errorResponse.ts


export interface ErrorResponse {
  
  message: string;
}

apiClient/schemas/index.ts

export * from './colorListResponse';
export * from './errorResponse';

そして今回は設定(orval.config.ts)にて、output.client: 'react-query' を指定しているため、それらコードも生成されています。

生成された colorsAPI.ts(一部抜粋)

apiClient/colors/colorsAPI.ts(一部抜粋)

...省略

import { useQuery } from "@tanstack/react-query";
import type {
  QueryFunction,
  QueryKey,
  UseQueryOptions,
  UseQueryResult,
} from "@tanstack/react-query";

...省略



export function useGetApiColors
  TData = AwaitedReturnTypetypeof getApiColors>>,
  TError = ErrorResponse
>(options?: {
  query?: UseQueryOptions
    AwaitedReturnTypetypeof getApiColors>>,
    TError,
    TData
  >;
  request?: SecondParametertypeof customFetch>;
}): UseQueryResultTData, TError> & { queryKey: QueryKey } {
  const queryOptions = getGetApiColorsQueryOptions(options);

  const query = useQuery(queryOptions) as UseQueryResultTData, TError> & {
    queryKey: QueryKey;
  };

  query.queryKey = queryOptions.queryKey;

  return query;
}
...省略

いろいろごちゃごちゃしてますが、useGetApiColors が先ほどの getApiColors を React-Query の useQuery のように使えるカスタムフックになっています。

colorsAPI.msw.ts にはMSW用のモックデータおよびハンドラーが生成されています。

生成された colorsAPI.msw.ts

apiClient/colors/colorsAPI.msw.ts

import { HttpResponse, delay, http } from "msw";

import type { ColorListResponse, ErrorResponse } from "../schemas";

export const getGetApiColorsResponseMock = (): ColorListResponse => [
  "red",
  "green",
  "blue",
];

export const getGetApiColorsMockHandler = (
  overrideResponse?:
    | ColorListResponse
    | ((
        info: ParametersParameterstypeof http.get>[1]>[0]
      ) => PromiseColorListResponse> | ColorListResponse)
) => {
  return http.get("*/api/colors", async (info) => {
    await delay(1000);

    return new HttpResponse(
      JSON.stringify(
        overrideResponse !== undefined
          ? typeof overrideResponse === "function"
            ? await overrideResponse(info)
            : overrideResponse
          : getGetApiColorsResponseMock()
      ),
      { status: 200, headers: { "Content-Type": "application/json" } }
    );
  });
};

今回は最初の openapi.yaml に GET メソッドの一つしか用意していなかったので一つしか生成されていませんが、複数のメソッドおよびエンドポイントが記載されていれば、その分生成され、それらが最後の行の Handlers の関数(今回でいう getColorsAPIMock)に集約されます。
次の章でこちらの Handlers の関数を使用することで MSW サーバーに登録することができます。

MSW の導入

https://mswjs.io/

前の章では Orval を使用し API クライアントコードと同時に MSW 用のモックハンドラー (colorsAPI.msw.ts など)を生成しました。

この章から、生成されたモックハンドラーを活用するために、MSW(Mock Service Worker) をプロジェクトにセットアップし、開発時に API モックを有効にする手順を説明します。

とくに Next.js App Router は Pages Router に比べ、MSW のセットアップに若干の癖があり、方法によっては一部問題点*(2025/04/22現在)も存在します。それらを含めここでまとめて現在可能な導入手順を紹介します。

※ MSW そのものについては各種記事が豊富にありますのでそちらをご参照ください。

1. MSW のインストール

まず、MSW をインストールします。

$ npm install msw --save-dev

2. Service Worker スクリプトの初期化(ブラウザ環境用)

MSW をブラウザで動作させるためには、Service Worker スクリプトが必要です。
以下のコマンドを実行して、Next.js の公開ディレクトリ public/ に Service Worker スクリプト mockServiceWorker.js を生成します。

$ npx msw init public/ --save

実行後、public ディレクトリに mockServiceWorker.js ファイルが作成されていれば成功です。

  my-next-app/
  ├─ apiClient/
  ├─ app/
  ├─ public/
+ │   └─ mockServiceWorker.js #   ├─ schemas/
  │     └─ openapi.yaml
  ├─ orval.config.ts
  ├─ next.config.js
  ├─ package.json
  └─ tsconfig.json

この mockServiceWorker.js は、ブラウザ上で動作し、アプリケーションからのネットワークリクエスト(fetch など)を捕捉して MSW のモック処理に渡す役割を担います。public/ ディレクトリ配下に置くことで、Service Worker として正しく登録・動作させることができます。

3. MSW 起動に必要なファイルを作成

まず MSW 公式 Docs にもあるような、一般的な設定ファイルを作成します。

  my-next-app/
  ├─ apiClient/
  ├─ app/
  ├─ public/
  │   └─ mockServiceWorker.js
+ ├─ mocks/
+ │     ├─ browser.ts
+ │     ├─ server.ts
+ │     ├─ handlers.ts
  ├─ schemas/
  │     └─ openapi.yaml
  ├─ orval.config.ts
  ├─ next.config.js
  ├─ package.json
  └─ tsconfig.json

ここでは MSW の設定ファイルを格納する mocks/ ディレクトリを作成し、以下の3つの基本的なファイルを用意します。

  • handlers.ts: API のモック定義(リクエストハンドラー)を集約するファイルです。Orval が生成したハンドラーや、独自に作成したハンドラーをここにまとめます。
  • browser.ts: ブラウザ環境で MSW を動作させるための設定ファイルです。Service Worker をセットアップします。
  • server.ts: Node.js 環境で MSW を動作させるための設定ファイルです。

browser.ts

import { setupWorker } from 'msw/browser';
import { handlers } from './handlers';

export const worker = setupWorker(...handlers);

server.ts

import { setupServer } from 'msw/node';
import { handlers } from './handlers';

export const server = setupServer(...handlers);

handlers.ts

import { getColorsAPIMock } from "@/apiClient/colors/colorsAPI.msw";
import type { RequestHandler } from "msw";


const orvalHandlers = [...getColorsAPIMock()];


const originalHandlers: RequestHandler[] = [];


export const handlers: RequestHandler[] = [...originalHandlers, ...orvalHandlers];
  • handlers.tsには先ほど Orval で生成されたcolorsAPI.msw.ts内にあるgetColorsAPIMockをインポートしてきて入れています。
  • 本記事と異なるopenapi.yamlを使っている場合でも、生成されたOOO.msw.tsファイルの一番下の行に生成されていると思うので、各自ご確認ください。

apiClient/colors/colorsAPI.msw.ts

...省略
export const getColorsAPIMock = () => [getGetApiColorsMockHandler()];

また以下例のように、Orval で生成される Handler の引数に任意の値を渡すことで、レスポンス値に書き換えることもできます。こちらも適宜活用すると良いでしょう(参考

handler.ts

import { getGetApiColorsMockHandler } from "@/apiClient/colors/colorsAPI.msw";
...
const originalHandlers = [
  getGetApiColorsMockHandler(["rainbow", "superRainbow", "hyperRainbow"]),
];
...

このように getGetApiColorsMockHandler のような Orval が生成した関数を呼び出す際に引数を渡すことで、特定のシナリオ(例えばテスト時)で返すモックデータを簡単に上書きすることができます。

つづいて作成した browser.tsserver.ts を実行する機構を作ります。

4. MSW Provider コンポーネントの作成

MSW を起動するためのラッパーコンポーネントを作ります。(参考

  my-next-app/
  ├─ apiClient/
  ├─ app/
  ├─ public/
  ├─ mocks/
  ├─ schemas/
+ ├─ components/
+ │     ├─ MswClientProvider.tsx
+ │     └─ MswProvider.tsx
  ├─ orval.config.ts
  ├─ next.config.js
  ├─ package.json
  └─ tsconfig.json

components/MswClientProvider.tsx

"use client";
import { use } from "react";


const mockingEnabledPromise =
  typeof window !== "undefined"
    ? import("@/mocks/browser").then(async ({ worker }) => {
        await worker.start({ onUnhandledRequest: "bypass" });
      })
    : Promise.resolve();


export const MswClientProvider = ({
  children,
}: {
  children: React.ReactNode;
}) => {
  
  use(mockingEnabledPromise);
  return children;
};
  • MswClientProvider.tsx はクライアントコンポーネントから叩かれる API をモックするために用意します。
  • mockingEnabledPromise 内で、先ほど browser.ts に設定した MSW の worker を起動しています。worker 起動後にコンポーネントを描画したいので、React の use を使っています。

components/MswProvider.tsx

import { Suspense, type ReactNode } from "react";
import { MswClientProvider } from "./MswClientProvider";

if (process.env.NEXT_RUNTIME === "nodejs") {
  const { server } = await import("@/mocks/server");
  server.listen({ onUnhandledRequest: "bypass" });
}


export const MswProvider = ({ children }: { children: ReactNode }) => {
  return (
    Suspense fallback={null}>
      MswClientProvider>{children}MswClientProvider>
    Suspense>
  );
};
  • MswProvider はサーバーコンポーネントから叩かれる API をモックするために用意します。
  • コンポーネント内ではなく、そのまま外に server.ts で設定した MSW の処理を実行させています。
  • また先ほどの MswClientProvider を呼び出す親コンポーネントでもあり、 MswClientProvider の処理が終わるまでは Suspense で描画を待ちます。

定義した MSWProviderlayout.tsx などの API を使用する親コンポーネントで呼び出し、ラップします。

app/layout.tsx

import "./globals.css";
import { MswProvider } from "@/components/MswProvider";

export default function RootLayout({
  children,
}: Readonly  children: React.ReactNode;
}>) {
  return (
    html lang="ja">
      body>
+       MswProvider>{children}MswProvider>
      body>
    html>
  );
}

今回はアプリケーションのルートレイアウトである layout.tsx{children} でラップすることにより、全てのページ・コンポーネントがレンダリングされる前に MSW が起動されるようになります。

5. MSW の起動

コードが書けたらアプリケーションを実行し、ブラウザのコンソールに赤文字で「[MSW] Mocking enabled.」が出れば起動成功です!

別の MSW 設定方法

余談ですが、Next.js の Instrumentation を使用する方法(現地点では一部問題点あり)も紹介します。

興味のある方はお読みください。追加で設定する必要はありません。

別の MSW 設定方法

サーバーコンポーネントから叩かれる API をモックするために Next.js の Instrumentation を使用する方法があります。

https://nextjs.org/docs/app/building-your-application/optimizing/instrumentation

  my-next-app/
  ├─ apiClient/
  ├─ app/
  ├─ public/
  ├─ mocks/
  ├─ schemas/
  ├─ components/
+ ├─ instrumentation.ts
  ├─ orval.config.ts
  ├─ next.config.js
  ├─ package.json
  └─ tsconfig.json

instrumentation.ts

export async function register() {
  
  if (process.env.NEXT_RUNTIME === "nodejs") {
    const { server } = await import("@/mocks/server");
    server.listen();
  }
}

参考: add next.js app router example #101

こちらの instrumentation.ts の処理は Next.js のサーバインスタンスが起動された際に一度だけ実行されます。
これによりサーバーコンポーネントから叩かれる API 処理もモックすることが可能です。

そのためアプリケーション実行中にコード編集をするとうまく MSW によるモックが機能しなくなり、再度実行 npm run dev等 をし直す必要があります。

現在も対応が行われているようですが、未だ特定の解決法はないようです。

https://github.com/mswjs/examples/pull/101

ですので、個人的には前で紹介している MswProvider のようなラッパーコンポーネントを組み込む方法が良いかと思います。

もし根本から解決するのであれば、本アプリのフロントサーバーとは別に API モックサーバーを立て、環境変数でリクエスト先の本番 API サーバー/ API モックサーバーを切り替えるのも良いでしょう。

別で環境を構築しても良いですが、Vercel が提供する Turborepo を用いて、本アプリのフロントサーバーと API モックサーバーを立てると楽に構築できそうです。

https://turbo.build/docs

他にも良い方法があればぜひコメントで教えてください!!

使用例

ではいよいよ環境は整ったので、Orval で生成した関数を用いて API を叩くコンポーネントを作ってみましょう。

また今回は TanStack Query(React Query)も使うので、ここらでインストールしておきます。

$ npm install @tanstack/react-query

それではサーバーコンポーネントのサンプル SampleServer.tsx と、クライアントコンポーネントのサンプル SampleClient.tsx をつくり、それをトップページのファイル app/page.tsx で呼び出します。

  my-next-app/
  ├─ apiClient/
  ├─ app/
+ │     └─ page.tsx
  ├─ public/
  ├─ mocks/
  ├─ schemas/
  ├─ components/
  │     ├─ MswClientProvider.tsx
  │     ├─ MswProvider.tsx
+ │     ├─ SampleSever.tsx
+ │     └─ SampleClient.tsx
  ├─ instrumentation.ts
  ├─ orval.config.ts
  ├─ next.config.js
  ├─ package.json
  └─ tsconfig.json

app/page.tsx

import SampleClient from "@/components/SampleClient";
import SampleServer from "@/components/SampleServer";

const Page = () => {
  return (
    >
      SampleServer />
      SampleClient />
    >
  );
};

export default Page;

components/SampleSever.tsx

import { getApiColors } from "@/apiClient/colors/colorsAPI";
import { Suspense } from "react";

const Body: React.FC = async () => {
  const response = await getApiColors();

  return (
    >
      h2>Server Componenth2>
      {response.map((color, i) => (
        p key={i}>{color}p>
      ))}
    >
  );
};

const SampleServer: React.FC = async () => {
  return (
    Suspense fallback={div>SampleServer Loading...div>}>
      Body />
    Suspense>
  );
};

export default SampleServer;
  • SampleServer コンポーネントは、’use client’ ディレクティブがないため、デフォルトで サーバーコンポーネントとして動作します。
  • 内部の Body コンポーネントで、Orval が生成した getApiColors 関数を直接 await してデータを取得しています。
  • データの取得が完了するまでの間は、SuspensefallbackSampleServer Loading... が表示されます。

components/SampleClient.tsx

"use client";
import { useGetApiColors } from "@/apiClient/colors/colorsAPI";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

const Body: React.FC = () => {
  const { data, isPending, error, isError } = useGetApiColors();

  if (isError) {
    return p>{error.message}p>;
  }

  if (isPending) {
    return p>SampleClient Loading...p>;
  }

  return (
    >
      h2>Client Componenth2>
      {data.map((color, i) => (
        p key={i}>{color}p>
      ))}
    >
  );
};

const SampleClient: React.FC = () => {
  
  const queryClient = new QueryClient();

  return (
    QueryClientProvider client={queryClient}>
      Body />
    QueryClientProvider>
  );
};

export default SampleClient;
  • SampleClient コンポーネントは、’use client’ ディレクティブが付与された クライアントコンポーネント です。
  • 内部の Body コンポーネントで、Orval が生成した React Query 用のカスタムフック useGetApiColors を使用してデータを取得しています。
  • TanStack Query(QueryClientProvider, useGetApiColors の中の useQuery) が、ローディング状態(isPending)、エラー状態(isError, error)、成功時のデータ(data)の管理を行ってくれます。

動作確認

それでは起動して動作確認してみます

しっかりと表示の確認ができました!

今回は openapi.yamlexample["red", "green", "blue"] と書いていて、かつ orval.config.tsuseExamples: true としていたので、その値が返ってきていますね。

再掲「schemas/openapi.yaml」「orval.config.ts」

schemas/openapi.yaml

...
    
    ColorListResponse:
      description: 色の文字列の配列
      type: array
      items:
        type: string
      example: ["red", "green", "blue"] 
...

orval.config.ts

...
export default defineConfig({
  color_api: {
    output: {
      mock: {
        type: "msw",
        useExamples: true, 
      },
    },
  },
});

「3. MSW 起動に必要なファイルを作成」の章でも話しましたが、モックのレスポンス値を変えたい場合は handler.tsoriginalHandlers に任意の MSW の Handler を追加すると良いでしょう。

再掲「mocks/handler.ts」

mocks/handler.ts

import { getGetApiColorsMockHandler } from "@/apiClient/colors/colorsAPI.msw";
...
const originalHandlers = [
+  getGetApiColorsMockHandler(["rainbow", "superRainbow", "hyperRainbow"]),
];
...

また序盤にも戻りますが、orval.config.ts の設定によってもモックのレスポンスを変えられます。

再掲「orval.config.ts」

orval.config.ts

export default defineConfig({
  color_api: {
    output: {
      mock: {
        type: "msw",
        useExamples: true, 
        generateEachHttpStatus: true, 
      },
      override: {
        mock: {
          required: true, 
        },
      },
    },
  ...
  },
});

ぜひ色々設定をいじって確かめてみてください!

まとめ

本記事では、Next.js(App Router)環境に、Orval と MSW を導入し、API クライアントコードの実装とモック環境の構築例を紹介しました。

Orval と MSW を用いることで比較的簡単に、

  • 型安全な API クライアントコードの自動生成
  • API スキーマと一貫性のあるモック環境の構築

が可能になります。

ぜひご自身のプロジェクトでも導入を検討してみてください。

今回紹介した手順を参考になれば幸いです!

フラッグシティパートナーズ海外不動産投資セミナー 【DMM FX】入金

Source link

Views: 0

RELATED ARTICLES

返事を書く

あなたのコメントを入力してください。
ここにあなたの名前を入力してください

- Advertisment -

Most Popular