【30分でできるアプリ】GraphQL × TypeScript × React入門|作って学ぶAPI連携(コード完全解説付き)


はじめに

GraphQLって最近よく聞くけど、結局何がいいの?
難しそうで手を出せない…

そんな方に向けて、この記事では「React + TypeScriptで最小のGraphQLアプリを作る」ことで、
GraphQLの仕組みと、型安全なAPI通信の魅力を体感してもらいます。

Reactの基本だけで動くので、今すぐローカル環境で試せる内容です!


作るもの:GitHubのリポジトリ一覧を表示するアプリ

入力フォームにGitHubユーザー名を入れると、その人の公開リポジトリ一覧が表示されるアプリを作ります。


1. GraphQLとは?RESTとの違いを3行で

REST APIGraphQL
エンドポイントごとに固定のレスポンスクライアントが必要な情報だけ取得できる
複数リクエストになりがち1回のクエリでまとめて取得可能
JSON構造が決められているクエリで構造を指定できる

つまりGraphQLは、「欲しい情報だけを指定して取れるAPI」です。


2. 開発環境の準備(Vite + React + TypeScript)

ディレクトリ構成(最終的にこうなります)

src/
├── App.tsx
├── components/
│ └── RepoList.tsx
├── graphql/
│ └── queries.ts
├── main.tsx
.env

① プロジェクトの作成

まずは、Vite で新しい React + TypeScript プロジェクトを作成します。

npm create vite@latest graphql-demo --template react-ts
  • graphql-demo:プロジェクトのフォルダ名(お好きな名前に変えてOK)
  • --template react-ts:React + TypeScript テンプレートを指定

実行すると、対話形式で以下の質問が表示されます。

フレームワークの選択(Choose a framework)

✔ Select a framework: › - Use arrow-keys. Return to submit.
❯ vanilla
vue
react
preact
lit
svelte

react を選択して Enter

バリアントの選択(Select a variant)

✔ Select a variant: › - Use arrow-keys. Return to submit.
❯ TypeScript
JavaScript

TypeScript を選択して Enter

完了すると、graphql-demo というディレクトリが作成され、その中にプロジェクトのファイルが一式用意されます。


② ディレクトリに移動して依存パッケージをインストール

cd graphql-demo
npm install
  • cd graphql-demo:作成したプロジェクトの中に移動します
  • npm install:依存モジュールをすべてインストールします

これをしないと npm run dev などが動きません。


③ Apollo Client と GraphQL 関連パッケージを追加

npm install @apollo/client graphql

このコマンドで、以下の2つのパッケージをインストールします:

  • @apollo/client:React 向け Apollo Client ライブラリ(GraphQLとの通信を簡単にする)
  • graphql:GraphQLクエリの構文解析や型定義などの内部処理用

④ 完了メッセージと確認

ここまでで準備は完了です。以下のように確認できます:

npm run dev

👆 これで開発サーバーが起動し、ブラウザで http://localhost:5173 が開くはずです。


3. GitHub GraphQL APIの準備

1. アクセストークンを取得

  1. GitHubの Developer Settings にアクセス
  2. Generate new token (classic) を選択
  3. スコープに public_repo をチェック(リードオンリーで十分)
  4. トークンを発行し、コピーしておきます

2. .envファイルを作成する

プロジェクトのルートに以下 .env ファイルを自分で新規作成してください。

VITE_GITHUB_TOKEN=[ここに取得したトークンを貼り付け]

.env は公開しないように .gitignore しておきましょう!


4. Apollo Clientのセットアップ

src/main.tsx

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import {
ApolloClient,
InMemoryCache, 
ApolloProvider,
} from '@apollo/client';

const client = new ApolloClient({
uri: 'https://api.github.com/graphql',
headers: {
Authorization: `Bearer ${import.meta.env.VITE_GITHUB_TOKEN}`,
},
cache: new InMemoryCache(),
});

ReactDOM.createRoot(document.getElementById('root')!).render(
<ApolloProvider client={client}>
<App />
</ApolloProvider>
);

コード解説

const client = new ApolloClient({
uri: 'https://api.github.com/graphql',

→ GitHubのGraphQL APIエンドポイントに接続するための設定です。ここに向けてクエリを送信します。

headers: {
  Authorization: `Bearer ${import.meta.env.VITE_GITHUB_TOKEN}`,
},

.env ファイルに記載した GitHub のアクセストークンを使って、APIへ認証付きでリクエストを送るようにしています。

cache: new InMemoryCache(),

→ データのキャッシュを有効にすることで、Apollo Client が取得済みのデータを再利用し、パフォーマンスを向上させます。

<ApolloProvider client={client}>
  <App />
</ApolloProvider>

→ アプリ全体を ApolloProvider で囲むことで、useQuery などの Apollo Hooks をあらゆる子コンポーネントで利用できるようにします。


5. クエリの定義とデータ取得

src/graphql/queries.ts

import { gql } from '@apollo/client';

export const GET_REPOS = gql`
query GetRepos($login: String!) {
user(login: $login) {
repositories(first: 10, orderBy: { field: UPDATED_AT, direction: DESC }) {
nodes {
id
name
url
}
}
}
}
`;

コード解説

export const GET_REPOS = gql`
  query GetRepos($login: String!) {

GET_REPOS は GraphQL のクエリ(取得処理)を定義しています。$login という変数を受け取る形で、後から任意のユーザー名を渡せるようにしています。


user(login: $login) {

→ GitHubユーザーを取得するためのフィールドです。GraphQL ではこのように、クエリの中で関数のように引数(ここでは login)を渡せます。


repositories(first: 10, orderBy: { field: UPDATED_AT, direction: DESC }) {

→ そのユーザーのリポジトリ一覧を、更新日時の降順(新しい順)で最大10件取得するようにしています。

nodes {
  id
  name
  url
}

→ 実際に取り出す情報の中身です。id(一意の識別子)、name(リポジトリ名)、url(リンク)だけに絞って取得します。



src/components/RepoList.tsx

import { useQuery } from '@apollo/client';
import { GET_REPOS } from '../graphql/queries';

type Props = {
username: string;
};

export const RepoList = ({ username }: Props) => {
const { loading, error, data } = useQuery(GET_REPOS, {
variables: { login: username },
skip: !username,
});

if (!username) return <p>ユーザー名を入力してください</p>;
if (loading) return <p>読み込み中...</p>;
if (error) return <p>エラーが発生しました:{error.message}</p>;

return (
<ul>
{data.user.repositories.nodes.map((repo: any) => (
<li key={repo.id}>
<a href={repo.url} target="_blank" rel="noreferrer">
{repo.name}
</a>
</li>
))}
</ul>
);
};

コード解説

APIの呼び出しから状態ごとの分岐(未入力・ロード中・エラー時・表示)までを RepoList コンポーネントで一貫して管理しています。

import { useQuery } from '@apollo/client';
import { GET_REPOS } from '../graphql/queries';

→ GraphQLクエリを実行するための useQuery フックを Apollo から読み込み、前ステップで定義した GET_REPOS をインポートしています。

type Props = {
  username: string;
};

→ このコンポーネントが受け取る props(親コンポーネントから渡ってくる値)の型を定義しています。username という文字列型のプロパティを想定しています。

const { loading, error, data } = useQuery(GET_REPOS, {
  variables: { login: username },
  skip: !username,
});

const { loading, error, data } = ...は、JavaScript の分割代入という書き方です。useQuery を実行すると、以下の3つの状態を返します:

変数名意味
loadingデータを読み込んでいる最中かどうか(true/false)
errorクエリ実行中にエラーが発生した場合、そのエラー情報
dataクエリが成功したときに返ってくるデータ(今回で言うとリポジトリ一覧)

useQuery フックは、「GraphQLのクエリをReactで使うための仕組み」です。 GraphQLクエリを実行し、結果を取得する処理です。

variables は GraphQL の変数(今回で言うと $login)に渡す値。

skipusername が空のときにクエリの実行をスキップするためのオプションです。

if (!username) return <p>ユーザー名を入力してください</p>;

username が未入力の場合、クエリを実行しないようにして、ユーザーへの指示メッセージを表示します。

if (loading) return <p>読み込み中...</p>;

→ クエリのレスポンスが返ってくるまでの間に表示するローディングメッセージです。

if (error) return <p>エラーが発生しました:{error.message}</p>;

→ APIからの取得中に何らかのエラーが起きた場合の処理です。

{data.user.repositories.nodes.map((repo: any) => (
  <li key={repo.id}>
    <a href={repo.url} target="_blank" rel="noreferrer">
      {repo.name}
    </a>
  </li>
))}

→ 取得したリポジトリのリスト(nodes)を1件ずつ <li> に展開して表示しています。GitHub上のリポジトリにリンクする形です。


6. フォームと表示処理

src/App.tsx

import { useState } from 'react';
import { RepoList } from './components/RepoList';

const App = () => {
const [username, setUsername] = useState('');

return (
<div style={{ padding: '2rem' }}>
<h1>GitHubのリポジトリ一覧</h1>
<input
type="text"
placeholder="GitHubユーザー名を入力"
value={username}
onChange={(e) => setUsername(e.target.value)}
style={{ padding: '0.5rem', marginBottom: '1rem' }}
/>
<RepoList username={username} />
</div>
);
};

export default App;

コード解説

全体として、この App.tsx
ユーザー名の入力 → RepoList.tsx への連携 → API取得
という一連の流れをコントロールする中核です。

import { useState } from 'react';

→ React の useState フックを使って、状態(この場合は入力された GitHub ユーザー名)を管理します。

const [username, setUsername] = useState('');

username は現在の入力値を保持する状態変数で、初期値は空文字列。setUsername で値の更新が可能です。

<input
  type="text"
  placeholder="GitHubユーザー名を入力"
  value={username}
  onChange={(e) => setUsername(e.target.value)}
/>

→ 入力フォームの定義です。ユーザーが文字を入力するたびに setUsername を使って username を更新しています。
onChange イベントで文字の入力をリアルタイムに反映しています。
value 属性で状態とフォームを連動させています(いわゆる「Controlled Component」)。

<RepoList username={username} />

→ 入力された usernameRepoList コンポーネントに渡し、そのユーザーのリポジトリ一覧を表示させるようにしています。

ここでは useState を使って入力フォームの状態を管理しています。


7.リポジトリ一覧表示アプリが完成!

開発環境を開くと…

アプリのUIが表示されました!!

そして、適切なユーザー名を入力すると…

無事、リポジトリ一覧が表示されました!!

また、これらは各リポジトリへのgithubリンクにもなっているので、ぜひクリックして確認してみてください。

8. よくあるエラーと対処法

エラー原因対処法
401: Unauthorizedトークンのミス or 未設定.env に正しいトークンを設定し直す
Network errorCORS, ネット接続問題などGitHub APIが落ちていないか確認
undefinednullクエリの構文間違いやskip忘れコンソールでクエリをデバッグしてみる

まとめ

  • GraphQLはクエリベースで欲しい情報だけ取得できる
  • TypeScriptと組み合わせると、型の恩恵が非常に大きい
  • Apollo Clientを使えば、Reactアプリでも導入はとても簡単!

次に読むべき記事はこちら

今回の記事では「GraphQLのクエリ(読み取り)」を使って、GitHubのリポジトリ一覧を取得するアプリを作成しました。
次のステップとして、「Mutation(更新)」を使った操作にもチャレンジしてみましょう!

【GraphQL実践】Mutationで『いいね』機能を実装!Apollo Client応用ガイド

この記事では、今回のアプリに「スター(いいね)」機能を追加しながら、GraphQLのMutationの使い方や、useMutationの構文・返り値の構造まで丁寧に解説しています。

GraphQLを使った双方向のデータ操作を実践的に学べる内容です。ぜひ併せてご覧ください!

参考リンク


コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です