はじめに
GraphQLって最近よく聞くけど、結局何がいいの?
難しそうで手を出せない…
そんな方に向けて、この記事では「React + TypeScriptで最小のGraphQLアプリを作る」ことで、
GraphQLの仕組みと、型安全なAPI通信の魅力を体感してもらいます。
Reactの基本だけで動くので、今すぐローカル環境で試せる内容です!
作るもの:GitHubのリポジトリ一覧を表示するアプリ
入力フォームにGitHubユーザー名を入れると、その人の公開リポジトリ一覧が表示されるアプリを作ります。

1. GraphQLとは?RESTとの違いを3行で
REST API | GraphQL |
---|---|
エンドポイントごとに固定のレスポンス | クライアントが必要な情報だけ取得できる |
複数リクエストになりがち | 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. アクセストークンを取得
- GitHubの Developer Settings にアクセス
Generate new token (classic)
を選択- スコープに
public_repo
をチェック(リードオンリーで十分) - トークンを発行し、コピーしておきます
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
)に渡す値。
・skip
は username
が空のときにクエリの実行をスキップするためのオプションです。
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} />
→ 入力された username
を RepoList
コンポーネントに渡し、そのユーザーのリポジトリ一覧を表示させるようにしています。
ここでは
useState
を使って入力フォームの状態を管理しています。
7.リポジトリ一覧表示アプリが完成!
開発環境を開くと…

アプリのUIが表示されました!!
そして、適切なユーザー名を入力すると…

無事、リポジトリ一覧が表示されました!!
また、これらは各リポジトリへのgithubリンクにもなっているので、ぜひクリックして確認してみてください。
8. よくあるエラーと対処法
エラー | 原因 | 対処法 |
---|---|---|
401: Unauthorized | トークンのミス or 未設定 | .env に正しいトークンを設定し直す |
Network error | CORS, ネット接続問題など | GitHub APIが落ちていないか確認 |
undefined や null | クエリの構文間違いやskip 忘れ | コンソールでクエリをデバッグしてみる |
まとめ

- GraphQLはクエリベースで欲しい情報だけ取得できる
- TypeScriptと組み合わせると、型の恩恵が非常に大きい
- Apollo Clientを使えば、Reactアプリでも導入はとても簡単!
次に読むべき記事はこちら
今回の記事では「GraphQLのクエリ(読み取り)」を使って、GitHubのリポジトリ一覧を取得するアプリを作成しました。
次のステップとして、「Mutation(更新)」を使った操作にもチャレンジしてみましょう!
【GraphQL実践】Mutationで『いいね』機能を実装!Apollo Client応用ガイド
この記事では、今回のアプリに「スター(いいね)」機能を追加しながら、GraphQLのMutationの使い方や、useMutation
の構文・返り値の構造まで丁寧に解説しています。
GraphQLを使った双方向のデータ操作を実践的に学べる内容です。ぜひ併せてご覧ください!
参考リンク
- 4ステップで作れるカウントアプリ|useState・useEffect・propsを実践で習得
- GraphQLとは?仕組みと導入メリット
- React入門ガイド(useStateやuseEffectが不安な人向け)
- GitHub GraphQL API公式ドキュメント
コメントを残す