react-query と graphql-request で型指定された GraphQL
13813 ワード
MagicBell のフロントエンドは React/TypeScript アプリケーションですが、バックエンドは Ruby で記述します.この記事では、クライアントをバックエンドに接続する方法と、API の重大な変更を防ぐ方法について説明します.
まず、明白な選択を邪魔にならないようにしましょう.
GraphQL スキーマに基づいて型が生成されるということは、バックエンド (GraphQL API) が重大な変更を導入したときに TypeScript が通知することを意味します.フロントエンドエンジニアとして、それが私の望みです!
GraphQL コード ジェネレーターは、指示があれば、完全に型指定された React フックを生成できますが、私は物事をシンプルに保つのが好きで、それによって TypedDocumentNode approach が好きです.この亜種は、使用している GraphQL クライアントを認識しません.つまり、
それを起動して実行するには、いくつかの開発依存関係をインストールする必要があります.
そして今、よりエキサイティングな部分は、コード生成構成 (
それでおしまい. Codegen はプロジェクト ルートから
有名な
小さいので
取得部分では、
ここで「トリッキー」な部分ですが、生成された
それがすべての力になる魔法のソースです.
この設定により、バックエンドに自信を持ってクエリを実行する方法が得られます.新しいクエリを作成するには、
たとえば、この logs query :
次に
最後に、必要なデータを取得するために、コンポーネントでそのフックを使用します.
以上です.
要約
GraphQL コード ジェネレーター
まず、明白な選択を邪魔にならないようにしましょう.
graphql-codegen
.それは簡単です.このツールを使用すると、GraphQL スキーマに基づいて TypeScript 型を生成できます.型指定されたクエリ、ミューテーション、フラグメント、およびオブジェクト型を考えてみてください.GraphQL スキーマに基づいて型が生成されるということは、バックエンド (GraphQL API) が重大な変更を導入したときに TypeScript が通知することを意味します.フロントエンドエンジニアとして、それが私の望みです!
GraphQL コード ジェネレーターは、指示があれば、完全に型指定された React フックを生成できますが、私は物事をシンプルに保つのが好きで、それによって TypedDocumentNode approach が好きです.この亜種は、使用している GraphQL クライアントを認識しません.つまり、
react-apollo
(または代替) に関連付けられていません.それを起動して実行するには、いくつかの開発依存関係をインストールする必要があります.
npm i -D
@graphql-codegen/cli
@graphql-codegen/typed-document-node
@graphql-codegen/typescript
@graphql-codegen/typescript-operations
@graphql-typed-document-node/core
そして今、よりエキサイティングな部分は、コード生成構成 (
codegen.yml
) です.コードに格納されたスキーマはありません.また、バックエンドが Ruby にあるため、graphql-codegen
はバックエンド ソース ファイルから型を抽出することもできません.代わりに、GraphQL エンドポイントを提供します.セットアップは簡単ですが、1 つの欠点は、新しい型を生成するときにサーバーが実行されている必要があることです.schema:
- http://localhost:3000/graphql:
headers:
X-MAGICBELL-API-KEY: "${MAGICBELL_API_KEY}"
documents: "./app/javascript/src/graphql/**/*.graphql"
generates:
./app/javascript/src/graphql/generated.ts:
plugins:
- typescript
- typescript-operations
- typed-document-node
それでおしまい. Codegen はプロジェクト ルートから
.env
ファイルを読み取り、それを使用して API ヘッダーを設定します. documents
は、GraphQL クエリが保存されるパスです.それらについては後で説明します.Graphql クライアント
有名な
@apollo/client
は使用しません.ダッシュボードには大きすぎるからです.さらに、REST から GraphQL に移行しているため、しばらくの間、両方に対処する必要があります. React Query はキャッシュ管理に優れており、REST と GraphQL の両方に使用できるため、それを使用します.小さいので
swr
の代わりに react-query
を検討しましたが、必要な基礎がいくつか欠けています.ミューテーションを管理するための明確な状態インジケーターまたは (確実な) ソリューションを考えてください.取得部分では、
graphql-request
を使用します. 1 か月あたりのインストール数は apollo とほぼ同じですが、way smaller であり、未解決の問題はそれほど多くありません.TypedDocumentNode と graphql-request
ここで「トリッキー」な部分ですが、生成された
graphql-request
を使用するには TypedDocumentNode
が必要です.そのために、カスタム フックを作成しました.import { useCallback } from 'react';
import { request } from 'graphql-request';
import { RequestDocument } from 'graphql-request/dist/types';
import { TypedDocumentNode } from '@graphql-typed-document-node/core';
import { useCurrentUser } from '../context';
export function useGraphqlRequest() {
const { apiKey } = useCurrentUser();
return useCallback(
<TDocument = any, TVariables = Record<string, any>>(
document: RequestDocument | TypedDocumentNode<TDocument, TVariables>,
variables?: TVariables,
) =>
request<TDocument, TVariables>('/graphql', document, variables, {
'X-MAGICBELL-API-KEY': apiKey,
}),
[apiKey],
);
}
それがすべての力になる魔法のソースです.
graphql-request
クライアントを返し、TypedDocumentNode
を使用してクエリから型を推測します.また、いくつかのデフォルトを graphql-request
に提供します.型注釈がなくても、これは、コード全体の複数の場所でオプション (ヘッダーなど) を設定できないようにする便利なフックになります.クエリの作成
この設定により、バックエンドに自信を持ってクエリを実行する方法が得られます.新しいクエリを作成するには、
*.graphql
で宣言されたパスのどこかにある codegen.yml#documents
ファイルに GraphQL 定義を書き込みます.たとえば、この logs query :
query logMessage($id: ID!) {
log(id: $id) {
id
createdAt
user {
firstName
lastName
email
}
notification {
title
content
actionUrl
}
}
}
次に
npx graphql-codegen
を実行し、react-query
を使用して作成したクエリ フックで生成された型を使用します.import { useQuery } from 'react-query';
import { useGraphqlRequest } from './useGraphqlRequest';
import { LogMessageDocument, LogMessageQuery } from './generated';
type UseLogMessageOptions = {
logId?: LogMessageQuery['log']['id'];
};
export function useLogMessage({ logId }: UseLogMessageOptions) {
const request = useGraphqlRequest();
return useQuery<LogMessageQuery['log']>(
['log-message', logId],
() => request(LogMessageDocument, { id: logId }).then((x) => x.log),
{ enabled: logId != null },
);
}
最後に、必要なデータを取得するために、コンポーネントでそのフックを使用します.
function LogDetails({ logId }: LogDetailsProps) {
const { data, status } = useLogMessage({ logId });
以上です.
data
は完全に入力されています.バックエンド エンジニアが現在のフロントエンドと互換性のない変更を導入した場合や、そもそも存在しなかったデータを使用しているとします.その場合、TypeScript はプル リクエストに対して実行されるチェックの一部としてエラーをスローすることで通知します.要約
graphql-codegen
を使用して GraphQL クエリを入力し、react-query
を使用してサーバー/クエリの状態を管理します. graphql-request
は codegen と react-query の間の接着剤であり、必要に応じて、GraphQL 用に型指定された fetch
です.この設定により、GraphQL クエリが MagicBell で壊れる可能性が減りました.
Reference
この問題について(react-query と graphql-request で型指定された GraphQL), 我々は、より多くの情報をここで見つけました
https://dev.to/smeijer/typed-graphql-with-react-query-graphql-request-3jj9
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
Reference
この問題について(react-query と graphql-request で型指定された GraphQL), 我々は、より多くの情報をここで見つけました https://dev.to/smeijer/typed-graphql-with-react-query-graphql-request-3jj9テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol