この記事の内容
前回、GraphQLの初心者がRailsでGraphQLを使えるようになるまでに調べたことをまとめて書きました。
GraphQLでデータを取得する作業のうち、
- 型の定義
- スキーマの書き方
までは記載できたのですが、肝心の**「どうやってデータを取得してくるか」**が長文になりすぎて書けなかったので、ここに記載します。
参考にしたのはこちらの記事と
こちらのチュートリアルなど
実際の実装方法は上記の記事の方が詳しいので、ここでは自分が担当したところでの実装で工夫していた点について主に記載していきます。
Apollo Clientを扱う
GraphQLの準備
既存の記事や公式チュートリアルの記載内容が大変優れているので、詳細はそちらに譲ります。ここではシンプルに手順だけ。
gem 'graphiql-rails'
こちらのgemをインストールして
$ bundle install
$ rails g graphql:install
のコマンドを実行したときに、routes.rbに以下の内容が記載されていると思います。
Rails.application.routes.draw do
post "/graphql", to: "graphql#execute"
# 後略
end
これによって、/graphqlのURLにPOSTでアクセスすることでGraphQLのメソッドが実行されます。
その後の方の定義などは前回の記事をご覧ください。
Apollo Clientの準備
apollo-clientをインストールし、
yarn add @apollo/client
appolo-clientを初期化します。
import {
ApolloClient,
InMemoryCache,
ApolloProvider
} from "@apollo/client";
// 解説します(★1)
const client = new ApolloClient({
uri: 'http://localhost:3000/graphql',
cache: new InMemoryCache()
});
// 解説します(★2)
export const App = () => {
return (
<ApolloProvider client={client} >
<Sample />
</ApolloProvider>
);
}
apollo-clientの初期化
まずはApolloClient()メソッドを用いてapollo-clientを初期化します。
以下の2つが必須オプションです。
const client = new ApolloClient({
uri: 'http://localhost:3000/graphql',
cache: new InMemoryCache()
});
-
uri...
apollo-clientがGraphQLの情報を受け取るところ。uriかlinkのどちらかが必須で、両方あった場合はlinkが優先される。 -
cache...
apollo-clientがクエリの実行結果をローカルに保存するために使用するもの。@apollo/clientに同梱されているInMemoryCacheがおすすめ。
詳細なオプションはこちら。
このサンプルではApp.jsxにて初期化をしていますが、初期化の内容を他のファイルに記載してApp.jsxに読み込むこともできました。
ApolloProviderをアプリ上方に設置
そして、ApolloProviderをアプリの可能な限り上方に設置します。これに先ほど初期化したApolloClientのインスタンスを渡すことで下層のコンポーネントでapollo-clientが使えるようになります。
export const App = () => {
return (
<ApolloProvider client={client} >
<Sample />
</ ApolloProvider>
);
}
クエリの実行
クエリを実行するにはuseQuery()メソッドを利用します。先程App.jsx内で呼び出した、Sample.jsx内で、このように記載します。
import React from 'react';
import { useQuery, gql } from "@apollo/client";
const GET_USERS = gql`
query GetUsers {
users {
id
name
email
}
}
`;
export const Sample = () => {
const {loading, error, data} = useQuery(GET_USERS); // 解説します
if (loading) return 'ロード中....';
if (error) return `Error ${error.message}`;
return (
<>
{data.users.map(user => (
<div key={user.id}>
<h1>{user.name}</h1>
<h2>{user.email}</h2>
</div>
)}
</>
)
};
useQueryメソッドはデフォルトで loading, error,dataの3つのプロパティを持つresultオブジェクトを返します。
それを分割代入でそれぞれ{loading, error, data}に代入しています。
-
loading...これが
trueである間、クエリはまだ実行中であり、結果はまだ返されていません。 -
error...クエリで1つ以上のエラーが発生した場合、このオブジェクトには、
graphQLErrorsの配列または単一のnetworkErrorが含まれます。 -
result...
GraphQLクエリの実行結果を含むオブジェクトです。
useQueryの詳細な仕様はこちら
完成!
これで、ユーザーの情報を画面に描画することができたはずです。(既存のアプリは実像がかなり異なるので、抜け漏れがあるかもしれませんが、見つけ次第修正します)
その他、
- nestしたオブジェクトの
GET - ID等を利用した単一オブジェクトの
GET - mutationを利用した
POSTやUPDATEメソッドの実行
はまだできていませんが、徐々に試したいと思います。(試し次第追記します)