フロントエンド開発といえば。
react アプリの初期化( npm init vite@latest <アプリ名> )

graphql-codegen を使って、フックを自動生成し tanstack query + graphql クエリを実行する

● graphql-codegen を使って、フックを自動生成し tanstack query + graphql クエリを実行する

npm i -D @graphql-codegen/cli
npm i -D @graphql-codegen/client-preset
npm i -D @graphql-codegen/typescript-react-query

codegen.ts

キャッシュを入れたいので、react-query を使います

import { CodegenConfig } from "@graphql-codegen/cli";

const config: CodegenConfig = {
  schema: "http://localhost:4100/graphql",
  documents: ["./src/graphql/**/*.graphql"],
  ignoreNoDocuments: true, // for better experience with the watcher
  hooks: { afterAllFileWrite: ["prettier --write"] },
  generates: {
    "./src/graphql/generated.ts": {
      plugins: [
        "typescript",
        "typescript-operations",
        "typescript-react-query",
        {
          add: {
            content: "// generated by graphql-codegen. DO NOT EDIT.",
          },
        },
      ],
      config: {
        fetcher: "fetch",
        // fetcher: {
        //   func: "graphql/custom-fetcher#useFetchData",
        //   isReactHook: true,
        // },
      },
    },
  },
};
export default config;

fetcher の指定でよく使うのは、"fetch", "graphql-request", または

        fetcher: {
          func: "./custom-fetcher#useFetchData",
          isReactHook: true,
        },

です。

・custom-fetcher を指定した場合

src/graphql/custom-fetcher.ts を以下のような内容で作成します (例、next.js + firebaesトークンを自動取得)

import { getAccessToken } from "@/libs/firebaseAuth";

export const useFetchData = <TData, TVariables>(
  query: string,
  options?: RequestInit["headers"],
): ((variables?: TVariables) => Promise<TData>) => {
  return async (variables?: TVariables) => {
    if (!process.env.NEXT_PUBLIC_API_BASE_URL) {
      throw new Error("NEXT_PUBLIC_API_BASE_URL is not set");
    }
    const url = process.env.NEXT_PUBLIC_API_BASE_URL + "/graphql";
    const token = await getAccessToken(true);
    const res = await fetch(url, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${token}`,
        ...(options ?? {}),
      },
      body: JSON.stringify({
        query,
        variables,
      }),
    });
    const json = await res.json();
    if (json.errors) {
      const { message } = json.errors[0] || "Error..";
      throw new Error(message);
    }
    return json.data;
  };
};

・gaphqlクエリの設置

src/graphql/queries/UsersFindAll.graphql

query UsersFindAll {
  usersFindAll {
    id
    email
    name
    authProvider
    authId
    createdAt
    updatedAt
  }
}

自動生成の実行

graphql-codegen --config codegen.ts

・コンポーネントでのhooksの使用(fetcher: "fetch"の場合)

  const { data } = useUsersFindAllQuery<UsersFindAllQuery>({
    endpoint: "http://localhost:4000/graphql",
    fetchParams: {
      headers: {
        "content-type": "application/json",
        "Authorization": `Bearer ${token}`,
      },
    },
  });

・コンポーネントでのhooksの使用(fetcher: "graphql/custom-fetcher#useFetchData" の場合)

  const { data } = useUsersFindAllQuery();

・キャッシュを利用する(fetcher: "graphql/custom-fetcher#useFetchData" の場合)

キャッシュ時間を無限にして取得する場合。

  const { data } = useUsersFindAllQuery(
    {},
    { staleTime: Infinity, cacheTime: Infinity },
  );

参考 : https://bit.ly/3WplbNO

No.2345
06/09 11:09

edit