Webアプリケーション開発において、APIとの通信は必須のスキルとなっています。フロントエンドからバックエンドへのデータの取得や送信を効率的に行うために、様々なライブラリやツールが存在します。この記事では、最も一般的に使用されている4つの通信方法(fetch, Axios, SWR, React Query)について詳しく解説し、それぞれの特徴や使い分けについて紹介します。
目次
JavaScriptネイティブのfetch API
基本概念
fetch
APIは、モダンブラウザに組み込まれている標準のAPIで、HTTPリクエストを行うための基本的な機能を提供します。追加のライブラリをインストールする必要がないため、小規模なプロジェクトやシンプルなリクエストに適しています。
基本的な使い方
// GETリクエストの例
fetch('https://api.example.com/data')
.then(response => {
// レスポンスが成功(200-299)でない場合はエラーをスロー
if (!response.ok) {
throw new Error('Network response was not ok: ' + response.status);
}
return response.json(); // JSONとしてパース
})
.then(data => {
console.log('Success:', data);
})
.catch(error => {
console.error('Error:', error);
});
// POSTリクエストの例
fetch('https://api.example.com/data', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
title: 'New Post',
content: 'This is the content'
})
})
.then(response => response.json())
.then(data => console.log('Success:', data))
.catch(error => console.error('Error:', error));
fetchの特徴
メリット
- 追加のライブラリが不要(モダンブラウザに標準搭載)
- Promiseベースで非同期処理が書きやすい
- シンプルなAPI設計
デメリット
- エラーハンドリングが少し複雑(ネットワークエラーのみをキャッチし、HTTP 400/500エラーはデフォルトでは拒否されない)
- JSONのパースを手動で行う必要がある
- リクエストのキャンセル機能が実装されていない(AbortControllerを使用する必要がある)
- IEではサポートされていない(ポリフィルが必要)
より使いやすいAxios
基本概念
Axiosは、ブラウザとNode.jsの両方で動作する人気のあるHTTPクライアントライブラリです。fetchよりも機能が豊富で、使いやすいAPIを提供します。
インストール
npm install axios
# または
yarn add axios
基本的な使い方
import axios from 'axios';
// GETリクエスト
axios.get('https://api.example.com/data')
.then(response => {
console.log('Success:', response.data);
})
.catch(error => {
console.error('Error:', error);
});
// POSTリクエスト
axios.post('https://api.example.com/data', {
title: 'New Post',
content: 'This is the content'
})
.then(response => {
console.log('Success:', response.data);
})
.catch(error => {
console.error('Error:', error);
});
// async/awaitを使用した例
async function fetchData() {
try {
const response = await axios.get('https://api.example.com/data');
console.log('Success:', response.data);
} catch (error) {
console.error('Error:', error);
}
}
高度な使い方
// Axiosインスタンスの作成(共通設定)
const api = axios.create({
baseURL: 'https://api.example.com',
timeout: 5000,
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
// インターセプターの使用
api.interceptors.request.use(config => {
// リクエスト送信前の処理
console.log('Request sent:', config);
return config;
}, error => {
return Promise.reject(error);
});
api.interceptors.response.use(response => {
// レスポンス受信後の処理
console.log('Response received:', response);
return response;
}, error => {
// エラーハンドリング
if (error.response && error.response.status === 401) {
// 認証エラー時の処理
}
return Promise.reject(error);
});
// 複数のリクエストを並行して行う
axios.all([
api.get('/users'),
api.get('/posts')
])
.then(axios.spread((usersResponse, postsResponse) => {
console.log('Users:', usersResponse.data);
console.log('Posts:', postsResponse.data);
}))
.catch(error => {
console.error('Error:', error);
});
Axiosの特徴
メリット
- JSON変換を自動的に行う
- リクエストとレスポンスのインターセプター機能
- リクエストのキャンセル機能
- タイムアウト設定
- クロスサイトリクエストフォージェリ(CSRF)保護
- ブラウザとNode.jsの両方で使用可能
- 400/500エラーレスポンスを自動的にエラーとして処理
デメリット
- 追加のライブラリとしてインストールが必要
- 小規模なプロジェクトでは過剰な場合もある
データ取得のためのSWR
基本概念
SWR(Stale-While-Revalidate)は、Vercelが開発したReactフックベースのデータフェッチライブラリです。「古いデータを表示しながら再検証する」という戦略を採用しており、キャッシュからデータを素早く表示しつつ、バックグラウンドで最新データを取得することで、UXを向上させます。
インストール
npm install swr
# または
yarn add swr
基本的な使い方
import useSWR from 'swr';
// フェッチャー関数の定義
const fetcher = url => fetch(url).then(res => res.json());
function UserProfile({ userId }) {
const { data, error, isLoading } = useSWR(
`/api/users/${userId}`,
fetcher
);
if (error) return <div>エラーが発生しました</div>;
if (isLoading) return <div>ロード中...</div>;
return (
<div>
<h1>{data.name}</h1>
<p>Email: {data.email}</p>
</div>
);
}
Axiosと組み合わせる
import useSWR from 'swr';
import axios from 'axios';
const fetcher = url => axios.get(url).then(res => res.data);
function Posts() {
const { data, error, isLoading } = useSWR('/api/posts', fetcher);
// 以下同様...
}
ミューテーション(データの更新)
import useSWR, { mutate } from 'swr';
import axios from 'axios';
function TodoList() {
const { data: todos } = useSWR('/api/todos', fetcher);
async function markAsCompleted(id) {
// 楽観的UI更新
mutate(
'/api/todos',
todos.map(todo =>
todo.id === id ? { ...todo, completed: true } : todo
),
false // 再検証しない
);
// APIリクエスト
await axios.patch(`/api/todos/${id}`, { completed: true });
// キャッシュデータを再検証
mutate('/api/todos');
}
return (
<ul>
{todos?.map(todo => (
<li key={todo.id}>
{todo.title}
{!todo.completed && (
<button onClick={() => markAsCompleted(todo.id)}>
完了
</button>
)}
</li>
))}
</ul>
);
}
SWRの特徴
メリット
- 自動再検証(フォーカス時、ネットワーク再接続時など)
- デデュプリケーション(重複リクエストの排除)
- キャッシュの管理
- ページネーション、無限スクロールのサポート
- タイプセーフ(TypeScriptサポート)
- 楽観的UI更新
- 比較的小さなパッケージサイズ
デメリット
- 主にGETリクエストに特化している
- 複雑なキャッシュ無効化シナリオでは扱いにくい場合がある
- React専用(他のフレームワークには対応していない)
強力なデータ管理ツールReact Query
基本概念
React Query(TanStack Query)は、サーバーの状態管理に特化したライブラリで、データのフェッチング、キャッシング、同期、更新を効率的に行うことができます。SWRと同様のメリットを持ちつつ、より多くの機能と柔軟性を提供します。
インストール
npm install @tanstack/react-query
# または
yarn add @tanstack/react-query
セットアップ
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
// クライアントの作成
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 5 * 60 * 1000, // 5分間はデータを古いと見なさない
cacheTime: 30 * 60 * 1000, // 30分間キャッシュを保持
retry: 1, // エラー時に1回再試行
},
},
});
function App() {
return (
<QueryClientProvider client={queryClient}>
{/* アプリケーションのコンポーネント */}
<YourApp />
{/* 開発ツール(開発環境のみ) */}
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
);
}
基本的な使い方(クエリ)
import { useQuery } from '@tanstack/react-query';
import axios from 'axios';
function Users() {
const { data, isLoading, error } = useQuery({
queryKey: ['users'],
queryFn: async () => {
const { data } = await axios.get('/api/users');
return data;
},
});
if (isLoading) return <div>ロード中...</div>;
if (error) return <div>エラー: {error.message}</div>;
return (
<ul>
{data.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
ミューテーション(データの更新)
import { useMutation, useQueryClient } from '@tanstack/react-query';
import axios from 'axios';
function AddUserForm() {
const queryClient = useQueryClient();
const mutation = useMutation({
mutationFn: newUser => {
return axios.post('/api/users', newUser);
},
onSuccess: () => {
// ユーザーが追加されたら、usersクエリを無効化して再フェッチを強制
queryClient.invalidateQueries({ queryKey: ['users'] });
},
});
const handleSubmit = event => {
event.preventDefault();
const formData = new FormData(event.target);
const newUser = {
name: formData.get('name'),
email: formData.get('email'),
};
mutation.mutate(newUser);
};
return (
<form onSubmit={handleSubmit}>
<input name="name" placeholder="名前" required />
<input name="email" placeholder="メール" required />
<button type="submit" disabled={mutation.isPending}>
{mutation.isPending ? '送信中...' : 'ユーザーを追加'}
</button>
{mutation.isError && <p>エラー: {mutation.error.message}</p>}
{mutation.isSuccess && <p>ユーザーが正常に追加されました!</p>}
</form>
);
}
依存クエリ
function UserPosts({ userId }) {
// ユーザー情報を取得
const { data: user, isLoading: isLoadingUser } = useQuery({
queryKey: ['user', userId],
queryFn: () => axios.get(`/api/users/${userId}`).then(res => res.data),
});
// ユーザーが取得できたら、そのユーザーの投稿を取得
const { data: posts, isLoading: isLoadingPosts } = useQuery({
queryKey: ['posts', userId],
queryFn: () => axios.get(`/api/users/${userId}/posts`).then(res => res.data),
// ユーザーが取得できるまで実行しない
enabled: !!user,
});
if (isLoadingUser) return <div>ユーザーの読み込み中...</div>;
if (isLoadingPosts) return <div>投稿の読み込み中...</div>;
return (
<div>
<h1>{user.name}の投稿</h1>
<ul>
{posts.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
);
}
React Queryの特徴
メリット
- 強力なキャッシュ管理
- 宣言的なクエリとミューテーション
- ページネーション、無限スクロール、懸念事項の分離
- デバッグ用の開発ツール
- サーバーサイドレンダリング(SSR)のサポート
- 楽観的アップデート
- 自動再試行と失敗したクエリの回復
- 依存クエリ(連鎖的なクエリ)
- クエリのキャンセル
デメリット
- 学習曲線がやや高い
- 小規模なプロジェクトでは機能が過剰な場合がある
- バンドルサイズが大きい(ただし、必要な機能のみを選択的にインポート可能)
それぞれの使い分け
fetchを選ぶケース
- 追加ライブラリを最小限に抑えたい場合
- シンプルな単一リクエストのみ必要な場合
- 小規模なプロジェクトやプロトタイプ
- ポリフィルを使用してIE対応を行える場合
Axiosを選ぶケース
- より便利なAPIと高度な機能が必要な場合
- インターセプターやリクエストキャンセルなどの機能が必要な場合
- ブラウザとNode.jsの両方で一貫したAPIを使用したい場合
- XMLHttpRequestベースのソリューションが必要な場合(古いブラウザのサポート)
SWRを選ぶケース
- Reactアプリケーションで主にデータ取得(GET)に焦点を当てている場合
- リアルタイムデータやユーザーエクスペリエンスを重視する場合
- 自動再検証、キャッシュ管理、ステータスの追跡などが必要な場合
- 小〜中規模のプロジェクトで、軽量なソリューションを求める場合
React Queryを選ぶケース
- 複雑なデータ操作と状態管理が必要な大規模なReactアプリケーション
- GET以外にも多くのミューテーション(POST、PUT、DELETEなど)を扱う場合
- 高度なキャッシュ制御や複雑なフェッチング戦略が必要な場合
- クエリの依存関係を管理する必要がある場合
- デバッグツールとエコシステムの充実度を重視する場合
まとめ
4つのAPIとの通信方法を比較してきましたが、それぞれに強みと弱みがあります。プロジェクトの規模や要件に応じて適切なツールを選択することが重要です。
- fetch: シンプルで標準的、小規模プロジェクトに最適
- Axios: 使いやすく機能が豊富、多くのユースケースに対応
- SWR: Reactでのデータ取得に特化した軽量ライブラリ
- React Query: 複雑なデータ管理と状態を必要とする大規模プロジェクト向け
実際のプロジェクトでは、これらを組み合わせて使用することも珍しくありません。例えば、React QueryやSWRのフェッチャー関数としてAxiosを使用するなど、それぞれの長所を活かした構成も検討してみてください。
最終的には、チームの経験、プロジェクトの要件、パフォーマンス考慮事項などを総合的に判断して、最適なソリューションを選択することをお勧めします。
コメント