GraphQLサーバーからのデータフェッチ方法はSSGやサーバー側が用意したSDKなど多様にありますが、 最近使ったApollo Clientが使いやすかったので紹介します。
なお、実装例はNext.jsを使用してGitHub GraphQL APIからデータフェッチを行います。
Apollo Clientがおすすめな理由
公式サイトに色々理由が書いてありますが、この中で一番の理由はuseQueryフックがデフォルトで用意されていることかと思います。
これによって、自分でデータフェッチ用のコードを書く必要性がなくなり、従来より短いコードで実装ができるようになります。
なお、useQueryは多機能らしいのですが、自分はまだそこまで使いこなしていないのでご了承ください。
環境
- Next.js
- GitHub GraphQL APIでデータを取得するための準備が出来ている
(GitHubトークンを取得し、エクスプローラーなどでクエリーが作成できている)
※GraphQL APIの使い方は割愛します。
実装その1 パッケージのインストール
1から5までは公式サイトのステップ2~5をそのまま引用したものです。実装の基本は公式ドキュメントなので、まずは公式ドキュメントを見ながら手を動かしてみて、つまったら参考サイトを活用することをお勧めします。私も心掛けています。現実は厳しいですが・・・涙
インストールに関してはステップ2のとおり
npm install @apollo/client graphql
または
yarn add @apollo/client graphql
をインストールしてください。
実装その2 ApolloClientインスタンスの初期化(クライアント情報の作成)
ApolloClientのインスタンスを新たに生成します。
uriはエンドポイントを指定します。GitHub GraphQL APIのエンドポイントはこちら
公式の例にはありませんが、インスタンス作成の際にユーザーを認証する情報が必要になります。
GitHub GraphQL APIの場合だとheadersにアクセストークン情報が必要なので、それを追記しています。
なお、アクセストークン情報の直書きは厳禁です。環境変数を使いましょう。
ファイルはライブラリ関係だとlibが使われることが多いので、以下のパスに作成しました。
/src/lib/apollo/apolloClient.ts
export const apolloClient = new ApolloClient({
cache: new InMemoryCache(),
headers: { authorization: `Bearer ${process.env.GH_TOKEN}` },
uri: "https://api.github.com/graphql",
});
実装その3 クライアント情報をセットする。
その2で作成したクライアント情報をインポートしてReact側に渡します。
まずは_app.tsx(jsx)内に作成したクライアント情報(その2で作成したapolloClient)とApolloProviderをインポートします。
ApolloProviderはコンポーネントとして、<Component {...pageProps} />をラップする形で設置してください。
あとは、インポートしたクライアント情報を引数としてApolloProviderコンポーネントに渡せばOKです。
以下が_app.tsx(jsx)の例です。
import "../styles/globals.css";
import type { AppProps } from "next/app";
import { ApolloProvider } from "@apollo/client";
import { apolloClient } from "src/lib/apollo/apolloClient";
function MyApp({ Component, pageProps }: AppProps) {
return (
<ApolloProvider client={apolloClient}>
<Component {...pageProps} />
</ApolloProvider>
);
}
export default MyApp;
この作業により、どのページからもデータをフェッチすることができるようになりました。すごいですね!
実装その4 useQueryを使ってデータフェッチを行う
その3でどのページからもデータをフェッチすることができるとお伝えしましたが、方法はuseQueryを使用します。
まずはNext.jsのpages配下に任意のページ用ファイルを作成してください、
次に、そのページ内にエンドポイントからデータフェッチする際のクエリ情報を定義します。
内容は、5件分のリポジトリを最新の更新順に取得するもので、作成日や更新日、リポジトリのURL情報などがとれるように設定しています。
const GET_REPOSITORIES = gql`
query UseGitHubInfo {
user(login: "topaoad") {
name
url
repositories(last: 5, orderBy: { field: UPDATED_AT, direction: ASC }) {
totalCount
nodes {
name
description
createdAt
updatedAt
url
forkCount
stargazerCount
languages(orderBy: { field: SIZE, direction: DESC }, last: 10) {
totalCount
totalSize
edges {
node {
id
name
color
}
size
}
}
}
}
}
}
`;
もしクエリの作成がまだでしたら、以下のページで作成してください。
次に、先ほど定義したクエリ情報を使ってuseQueryでフェッチします。
ページのメインコンポーネント内のreturn文の前に以下のように書いてください。
すると、先ほどのクエリ情報を元にGitHub GraphQL APIからデータを取得し、data内に格納されます。
あとは、dataで取得したデータを使って、map関数などを用いて好き好きに実装をしてください!!
const Apollotest: NextPage = () => {
const { data, error, loading } = useQuery<UseGitHubInfoQuery>(
GET_REPOSITORIES
);
return
};
export default Apollotest;
実装その5 取得したデータに型定義を行う。
公式サイトの案内はここまでですが、実はもう一つやりたいことがあります。
それは、「取得したデータの自動型付け」です。
その4のuseQueryに<UseGitHubInfoQuery>というジェネリック型の型定義あるのにお気づきですか?
これは、GraphQL Code Generatorを用いて型定義ファイルを作成した際のものを引用しているのです。
詳しい作成方法はこちらの記事で紹介してますので、よければご覧ください。
引用したファイルについて簡単に説明しますと、型定義ファイル作成の際に標準で設定されているプラグイン
「Tpescript-operations」により、クエリと対になる型定義が自動で作成されます。
これを活用しているのです。
なお、typeの型定義名は「自分がつけたクエリ名+Query」となります。
私が命名したクエリ名がUseGitHubInfoだったので、下記例はUseGitHubInfoQueryとなります。
export type UseGitHubInfoQuery = {
__typename?: "Query";
user?: {
__typename?: "User";
name?: string | null;
url: any;
repositories: {
__typename?: "RepositoryConnection";
totalCount: number;
nodes?: Array<{
__typename?: "Repository";
name: string;
description?: string | null;
createdAt: any;
updatedAt: any;
url: any;
forkCount: number;
stargazerCount: number;
languages?: {
__typename?: "LanguageConnection";
totalCount: number;
totalSize: number;
edges?: Array<{
__typename?: "LanguageEdge";
size: number;
node: {
__typename?: "Language";
id: string;
name: string;
color?: string | null;
};
} | null> | null;
} | null;
} | null> | null;
};
} | null;
};
ちゃんと型があたっているか、試しにdataの上にマウスをホバーして確認します。
すると、ちゃんとあたっていることが確認できます!
まとめ
公式サイトに沿った基本的な説明でしたが、最後にプラスアルファで自動型付けの説明もさせていただきました。
自分もまだまだ応用が効かずにハマることが多々ありますが、精一杯概念の理解に努めることがスキルアップには必要不可欠だと思います。
もしご意見がありましたら、遠慮なくお申し付けください。
TwitterのDMなども大歓迎です!