search
LoginSignup
2

posted at

updated at

React + TypeScript: Apollo ClientのGraphQLクエリを使ってみる

Apollo ClientはReactで使える状態管理ライブラリです。ローカルとリモートのデータをGraphQLで扱えます。本稿でつくるのは、Apollo Client公式の「Get started with Apollo Client」で紹介されている作例です。ただし、TypeScriptを採り入れ、アプリケーションは簡単にモジュール分けしました。

Apollo Clientアプリケーションをつくる準備

Reactアプリケーションのひな形は、Create React Appでつくることにします。オプションとして--template typescriptを加えれば、TypeScriptの環境が簡単に加わえられて便利です(「Create React AppでTypeScriptが加わったひな形アプリケーションをつくる」参照)。

では、Apollo Clientをインストールしましょう。GraphQLも、依存があるのでインストールに加えてください(クエリを使わなくても必要です)。

npm install @apollo/client graphql

ApolloClientを初期化する

まず、ApolloClientのインスタンスをつくります。コンストラクタに渡すのはオプションオブジェクトで、ふたつの設定を加えました。uriはGraphQLサーバーのURLの文字列です。cacheはApollo Clientが読み込んだクエリ結果の保存先として必須で、多くの場合InMemoryCacheインスタンスが定められます。

  • uri: string - Apollo Clientが通信するGraphQLのエンドポイントURI。
  • cache: ApolloCache - クエリの結果をローカルに保存するためにApollo Clientが用いるべきキャッシュ(必須)。 @apollo/clientパッケージの提供するInMemoryCacheが推奨。

Reactのページへのデータの差し込みはあとにして、クエリを送ってみましょう(コード001)。ApolloClientインスタンスに対して呼び出すのはquery()メソッドです。引数には、gqlテンプレートリテラルで包んだ、クエリ文字列を渡してください。

コード001■ApolloClientでクエリを送る

src/App.tsx
import { useEffect } from 'react';
import {
	ApolloClient,
	InMemoryCache,
	gql,
} from '@apollo/client';

const client = new ApolloClient({
	uri: 'https://48p1r2roz4.sse.codesandbox.io',
	cache: new InMemoryCache(),
});
function App() {
	useEffect(() => {
		client
			.query({
				query: gql`
					query GetRates {
						rates(currency: "USD") {
							currency
						}
					}
				`,
			})
			.then((result) => console.log(result));
	}, []);
	return (
		<div>
			<h1>Apollo Client</h1>
		</div>
	);
}
export default App;

コードを実行すると、コンソールにクエリ結果のオブジェクトが示されるはずです(図001)。動きは、CodeSandboxに公開した以下のサンプル001でお確かめください1

図001■コンソールに出力されたクエリの結果

2203002-001.png

サンプル001■React + TypeScript: Using GraphQL queries with Apollo Client 01

ApolloProviderでReactのコンテクストにつなぐ

ApolloProviderコンポーネントを使うと、Apollo ClientをReactのコンテクストにつなげられます。仕組みはReactのContext.Providerと同じです。包まれたツリーの中のどのコンポーネントからでも、Apollo Clientのデータにアクセスできます。GraphQLのデータを用いる大もとのコンポーネントをApolloProviderに含めてください。プロパティclientに与えるのは、ApolloClientインスタンスです。

src/App.tsx
// import { useEffect } from 'react';
// import { ApolloClient, InMemoryCache, gql } from '@apollo/client';
import {

	ApolloProvider,

} from '@apollo/client';

function App() {
	/* useEffect(() => {

	}, []); */
	return (
		<ApolloProvider client={client}>
			<div>

			</div>
		</ApolloProvider>
	);
}

useQueryフックでデータを読み込む

ApolloProviderでReactのコンテクストにつなげたら、データをクエリで要求してページに読み込めます。用いるフックがuseQueryです。GraphQLのデータをReactと共有します。クエリは、ルートモジュール(src/App.tsx)に変数(ExchangeRates)で定めておきましょう。求めるプロパティとして、通貨(currency)のほかに為替レート(rate)を加えました。このあと定める子コンポーネント(ExchangeRates)のプロパティ(exchangeRates)にクエリを加えます。

src/App.tsx
import { ExchangeRates } from './ExchangeRates';

const EXCHANGE_RATES = gql`
	query GetExchangeRates {
		rates(currency: "USD") {
			currency
			rate
		}
	}
`;
function App() {
	return (
		<ApolloProvider client={client}>
			<div>

				<ExchangeRates exchangeRates={EXCHANGE_RATES} />
			</div>
		</ApolloProvider>
	);
}

useQueryフックに渡したクエリ(DocumentNode型)は、コンポーネントが描画されるたびに実行され、返されるのは新たな結果のオブジェクトです。為替レートを表示する子のモジュール(src/ExchangeRates.tsx)は、3つのプロパティを取り出しています(コード002)。

  • loading: boolean - ロード中かどうかのブール値。trueのときは、まだクエリの結果が返されていない。
  • error: ApolloError - クエリにエラーが起こったことを示すオブジェクト。
  • data: TData - GraphQLクエリが正しく実行されたときに得られる結果のデータ。

コードを実行すると、少しの間「Loading...」のテキストが示され、そのあと為替レートの一覧が表示されるでしょう。クエリの状態に応じて、コンポーネントがリアクティブに再描画されているということです。書き改めたルートモジュール(src/App.tsx)のコードも併せてまとめておきました。動きはCodeSandboxに公開した以下のサンプル002でお確かめください。

コード002■useQueryフックで読み込んだデータをページに表示する。

src/ExchangeRates.tsx
import { VFC } from 'react';
import {
	DocumentNode,
	useQuery,
} from '@apollo/client';

type Props = {
	exchangeRates: DocumentNode;
};
export const ExchangeRates: VFC<Props> = ({ exchangeRates }) => {
	const { loading, error, data } = useQuery(exchangeRates);
	if (loading) return <p>Loading...</p>;
	if (error) return <p>Error :(</p>;
	return data.rates.map(
		({ currency, rate }: { currency: string; rate: string }) => (
			<div key={currency}>
				<p>
					{currency}: {rate}
				</p>
			</div>
		)
	);
};
src/App.tsx
import {
	ApolloClient,
	ApolloProvider,
	InMemoryCache,
	gql
} from '@apollo/client';
import { ExchangeRates } from './ExchangeRates';

const client = new ApolloClient({
	uri: 'https://48p1r2roz4.sse.codesandbox.io',
	cache: new InMemoryCache(),
});
const EXCHANGE_RATES = gql`
	query GetExchangeRates {
		rates(currency: "USD") {
			currency
			rate
		}
	}
`;
function App() {
	return (
		<ApolloProvider client={client}>
			<div>
				<h1>Apollo Client</h1>
				<ExchangeRates exchangeRates={EXCHANGE_RATES} />
			</div>
		</ApolloProvider>
	);
}
export default App;

サンプル002■React + TypeScript: Using GraphQL queries with Apollo Client 02

  1. なお、CodeSandboxでは、graphqlのバージョンを16以上にすると、TypeErrorが出てしまうようです。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
2