16
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

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

Last updated at Posted at 2022-03-09

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が出てしまうようです。

16
3
0

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
  3. You can use dark theme
What you can do with signing up
16
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?