ReactでAxiosを使って複数のリクエストを同時に処理する方法を完全ガイド!初心者でもわかるAPI通信の基本
生徒
「ReactでAPI通信をするときに、複数のデータを一度に取りたいことがあります。そういうときはどうすればいいですか?」
先生
「その場合は、Axiosを使って複数のリクエストを同時に処理する方法があります。」
生徒
「一つずつ順番に処理するのではなく、まとめて同時にできるんですか?」
先生
「そうです。複数のリクエストを同時に実行すると、処理が速くなりユーザー体験もよくなりますよ。」
1. 複数リクエストを同時に処理する必要性
例えば、ブログアプリを作っていて「記事一覧」と「ユーザー情報」を同時に取得したいとします。順番に一つずつリクエストすると時間がかかりますが、同時にリクエストすれば待ち時間を短縮できます。これを「並列処理」と呼びます。
身近な例で言うと、スーパーでレジを一つだけ開けていると長い行列ができますが、複数のレジを同時に開けると待ち時間が減るのと同じ考え方です。
2. Axios.allを使う方法
Axiosにはaxios.allという便利な関数があります。これを使うと複数のリクエストを配列でまとめて実行し、すべての結果が返ってきてから処理を進めることができます。
import React, { useEffect, useState } from "react";
import axios from "axios";
function App() {
const [users, setUsers] = useState([]);
const [posts, setPosts] = useState([]);
useEffect(() => {
axios.all([
axios.get("https://jsonplaceholder.typicode.com/users"),
axios.get("https://jsonplaceholder.typicode.com/posts")
])
.then(axios.spread((userRes, postRes) => {
setUsers(userRes.data);
setPosts(postRes.data);
}))
.catch(() => {
console.error("データ取得に失敗しました");
});
}, []);
return (
<div>
<h2>ユーザー一覧</h2>
<ul>
{users.map(user => <li key={user.id}>{user.name}</li>)}
</ul>
<h2>投稿一覧</h2>
<ul>
{posts.slice(0,5).map(post => <li key={post.id}>{post.title}</li>)}
</ul>
</div>
);
}
export default App;
3. axios.spreadの役割
axios.spreadは、配列で返ってきたレスポンスをそれぞれの引数に分解して扱いやすくするための関数です。
これを使うと、userResとpostResのように名前をつけて読みやすくできます。
もし使わない場合はthen(([userRes, postRes]) => {...})のように書くこともできます。
4. async/awaitを使った書き方
最近のJavaScriptでは、async/awaitを使う書き方も人気です。これを使うと、コードがスッキリして読みやすくなります。
import React, { useEffect, useState } from "react";
import axios from "axios";
function App() {
const [users, setUsers] = useState([]);
const [posts, setPosts] = useState([]);
useEffect(() => {
const fetchData = async () => {
try {
const [userRes, postRes] = await Promise.all([
axios.get("https://jsonplaceholder.typicode.com/users"),
axios.get("https://jsonplaceholder.typicode.com/posts")
]);
setUsers(userRes.data);
setPosts(postRes.data);
} catch (error) {
console.error("エラーが発生しました", error);
}
};
fetchData();
}, []);
return (
<div>
<h2>ユーザーと投稿を同時取得</h2>
<p>ユーザー数: {users.length}</p>
<p>投稿数: {posts.length}</p>
</div>
);
}
export default App;
5. 実務での使いどころ
複数リクエストを同時に処理するのは、実務でもよく使います。例えば:
- ユーザー情報と設定情報を同時に取得する
- 複数のグラフに使うデータを一度に取得する
- 関連するAPIをまとめて呼び出して表示する
ただし、複数のリクエストがすべて終わるまで待つ必要があるため、どれか一つでも遅れると全体が遅れる点に注意しましょう。
6. エラーハンドリングの工夫
複数リクエストを同時に処理すると、どれか一つが失敗した場合に全体が止まってしまうことがあります。そのため、個別にエラーを扱いたい場合は工夫が必要です。
例えば、Promise.allSettledを使えば成功と失敗を区別して扱えます。
Promise.allSettled([
axios.get("https://jsonplaceholder.typicode.com/users"),
axios.get("https://jsonplaceholder.typicode.com/posts")
]).then(results => {
results.forEach(result => {
if (result.status === "fulfilled") {
console.log("成功:", result.value.data);
} else {
console.error("失敗:", result.reason);
}
});
});
7. まとめて管理するときの注意点
複数のリクエストを同時に処理すると便利ですが、以下の点に注意するとよいです。
- 不要なリクエストを同時に投げすぎない(サーバーに負担がかかる)
- 依存関係があるリクエストは同時処理せず順番に実行する
- ユーザーに「読み込み中」と表示して安心させる
この考え方を理解しておくと、ReactでのAPI通信をより効率的に設計できるようになります。
まとめ
React開発において、外部APIとの通信は避けては通れない重要なステップです。特に、アプリケーションの規模が大きくなるにつれて、一つの画面を表示するために「ユーザープロフィール」「投稿一覧」「通知設定」といった複数のデータを異なるエンドポイントから取得しなければならない場面が増えてきます。こうした際、一つひとつのリクエストを直列(順番)に処理してしまうと、ネットワークの待機時間が積み重なり、ユーザーを長く待たせてしまうことになります。
今回ご紹介したAxiosを使った並列リクエスト処理は、フロントエンドエンジニアにとって必須のテクニックです。axios.allやPromise.allを活用することで、複数のAPIリクエストを同時に発行し、すべてのレスポンスが揃ったタイミングで一括して状態(State)を更新することが可能になります。これにより、画面のレンダリング回数を最適化し、サクサクとした快適な操作感を提供できるようになります。
フロントエンド開発におけるベストプラクティス
実際の開発現場では、ただ「同時に送る」だけでなく、エラーハンドリングやローディング状態の管理もセットで考える必要があります。Promise.allは一つでもリクエストが失敗すると全体がエラーになってしまう特性があるため、個別のエラーを許容したい場合にはPromise.allSettledを使い分けるといった工夫が求められます。また、TypeScript(TSX)を使用しているプロジェクトでは、レスポンスの型定義をしっかり行うことで、データ取得後のバグを未然に防ぐことができます。
以下に、より実戦に近い形式でのReact TSXによるサンプルコードを掲載します。複数のAPIからデータを取得し、ローディング管理と型安全性を考慮した実装例です。
import React, { useEffect, useState } from "react";
import axios from "axios";
// APIから返ってくるデータの型を定義
interface User {
id: number;
name: string;
}
interface Post {
id: number;
title: string;
}
const MultiFetchComponent: React.FC = () => {
const [users, setUsers] = useState<User[]>([]);
const [posts, setPosts] = useState<Post[]>([]);
const [isLoading, setIsLoading] = useState<boolean>(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const fetchAllData = async () => {
try {
setIsLoading(true);
// 複数のリクエストを並列で実行
const [userResponse, postResponse] = await Promise.all([
axios.get<User[]>("https://jsonplaceholder.typicode.com/users"),
axios.get<Post[]>("https://jsonplaceholder.typicode.com/posts")
]);
setUsers(userResponse.data);
setPosts(postResponse.data);
} catch (err) {
setError("データの読み込み中にエラーが発生しました。");
console.error(err);
} finally {
setIsLoading(false);
}
};
fetchAllData();
}, []);
if (isLoading) return <div>読み込み中...</div>;
if (error) return <div>{error}</div>;
return (
<div className="container mt-4">
<h3>データ同時取得のデモ</h3>
<div className="row">
<div className="col-6">
<h4>ユーザー数: {users.length}名</h4>
</div>
<div className="col-6">
<h4>最新投稿数: {posts.slice(0, 5).length}件</h4>
</div>
</div>
</div>
);
};
export default MultiFetchComponent;
パフォーマンスを最大化するために
さらに応用的な内容として、リクエストの重複を避けるための「キャッシュ戦略」や、不要になったリクエストを中断する「AbortController」の利用なども検討してみてください。特にReactのuseEffectは、コンポーネントのクリーンアップ時に未完了のリクエストをキャンセルする処理を入れるのが作法です。
API通信はフロントエンドの肝です。Axiosを使いこなし、ユーザーにとってストレスのない高速なWebアプリケーションを目指しましょう。今回のまとめが、皆さんの開発スキルの向上に少しでも役立てば幸いです。
生徒
「先生、ありがとうございました!axios.allやPromise.allを使うと、複数のAPIをバラバラに待つ必要がなくなるんですね。一気にデータが揃う感覚がとても気持ちいいです。」
先生
「そうでしょう。特にスマホなどのモバイル回線では、リクエストの往復回数を減らすことが体感速度に直結します。今回の並列処理をマスターしたことで、アプリのパフォーマンスが一段階アップしましたね。」
生徒
「はい!でも、もし10個も20個もAPIがあったら、全部同時に投げても大丈夫なんですか?」
先生
「いい質問ですね。ブラウザには同時に接続できる数に制限がありますし、サーバー側も一度に大量のリクエストを受けると負荷がかかってしまいます。必要なものだけを厳選して送る、あるいは重要度の低いものは後から読み込むといった判断も大切ですよ。」
生徒
「なるほど。ただ技術を使うだけでなく、サーバーやユーザーの環境も考えるのがプロのエンジニアなんですね。次はTypeScriptでの型定義をもっと練習して、さらに安全な通信コードを書いてみたいと思います!」
先生
「その意気です!型定義をしっかりすれば、APIからどんなデータが来るかエディタ上で予測できるようになるので、開発効率もさらに上がりますよ。頑張ってくださいね。」