ReactでAxiosローディング状態を管理する方法を完全ガイド!初心者でもわかる非同期通信の基本
生徒
「ReactでAxiosを使ってデータを取ってくるとき、画面が止まっているように見えることがあります。どうすればわかりやすくできますか?」
先生
「それはローディング状態を管理する必要があります。ユーザーに『今データを読み込み中です』と見せる仕組みですね。」
生徒
「なるほど!それならボタンを押しても無反応に感じなくなりますね。」
先生
「その通りです。ReactとAxiosでのローディング管理を一緒にやってみましょう!」
1. ローディング状態とは?
ローディング状態とは、非同期処理の実行中に「いまデータを読み込んでいます」とユーザーへ伝えるための状態です。 ReactでAxiosなどを使って通信を行う場合、サーバーからの返答を待つ時間が必ず発生します。 その間に何も表示されていないと、ユーザーは操作が受け付けられていないように感じてしまいます。
そのため、ローディング状態を用意して画面表示を切り替えることで、 アプリが正常に動作していることを分かりやすく伝えられます。 これは見た目の問題だけでなく、ユーザーの安心感や操作ミス防止にもつながる重要な考え方です。
import React, { useState } from "react";
function LoadingSample() {
const [loading, setLoading] = useState(false);
const [message, setMessage] = useState("");
const startLoading = () => {
setLoading(true);
setTimeout(() => {
setMessage("データの読み込みが完了しました");
setLoading(false);
}, 2000);
};
return (
<div>
<button onClick={startLoading} disabled={loading}>
{loading ? "読み込み中..." : "処理を開始"}
</button>
{message && <p>{message}</p>}
</div>
);
}
export default LoadingSample;
このように、ローディング状態を使うことで、 処理の開始から完了までの流れをユーザーが自然に理解できるようになります。 Reactで非同期通信を扱う際は、まずこのローディング状態の考え方をしっかり押さえておくことが大切です。
2. Reactでローディング状態を管理する基本
Reactでローディング状態を管理する基本はとてもシンプルで、useStateでloadingのような真偽値の状態を用意します。
通信やデータ取得などの処理が「始まったらtrue」、処理が「終わったらfalse」に切り替えるだけです。
これだけで、読み込み中の表示を出したり、一覧を表示したりと、画面の見せ方を分かりやすく整理できます。
特に初心者のうちは「どのタイミングで画面が変わるのか」を意識すると理解が早いです。
loadingがtrueの間は読み込み中のメッセージを表示し、falseになったら取得したデータを表示する、という流れにすると迷いません。
まずはこの型を覚えておくと、Reactの非同期通信やAPI連携でも応用しやすくなります。
import React, { useState, useEffect } from "react";
import axios from "axios";
function App() {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(false);
useEffect(() => {
setLoading(true);
axios
.get("https://jsonplaceholder.typicode.com/users")
.then((res) => {
setData(res.data);
})
.catch(() => {
console.error("エラーが発生しました");
})
.finally(() => {
setLoading(false);
});
}, []);
if (loading) {
return <div>読み込み中です...</div>;
}
return (
<ul>
{data.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
export default App;
ここでのポイントは、ローディング中に「結果を表示しない」ように分岐している点です。
この分岐があるだけで、画面の状態がはっきりし、ユーザーも状況を理解しやすくなります。
まずはloadingの切り替えと表示の分岐をセットで覚えるのがおすすめです。
3. finallyで確実にローディングを終了する
Axiosではfinallyを使うと、通信が成功した場合も失敗した場合も、最後に必ず実行したい処理をひとまとめにできます。
ローディング管理で一番怖いのは「エラーが起きたときにloadingを戻し忘れて、ずっと読み込み中の表示が残る」ことです。
finallyにsetLoading(false)を書いておけば、どんな結果でも必ずローディングを終了できるので安心です。
初心者の方は、thenは「うまくいったとき」、catchは「失敗したとき」、そしてfinallyは「最後に必ずやること」と覚えると理解しやすいです。
画面の表示切り替えやボタンの無効化など、ローディングに関わる後片付けはfinallyにまとめるのが基本になります。
import React, { useState } from "react";
import axios from "axios";
function FinallySample() {
const [loading, setLoading] = useState(false);
const [text, setText] = useState("");
const fetchOnce = () => {
setLoading(true);
axios.get("https://jsonplaceholder.typicode.com/posts/1")
.then((res) => {
setText(res.data.title);
})
.catch(() => {
setText("通信に失敗しました");
})
.finally(() => {
// 成功でも失敗でも、最後に必ずローディングを終了する
setLoading(false);
});
};
return (
<div>
<button onClick={fetchOnce} disabled={loading}>
{loading ? "読み込み中..." : "取得する"}
</button>
{text && <p>{text}</p>}
</div>
);
}
export default FinallySample;
このように、ローディングを終了する処理をfinallyに置いておくと、
「成功したときだけ戻る」「失敗したときに戻らない」といったミスを防ぎやすくなります。
まずはローディング管理ではfinallyをセットで使う、という感覚を身につけるのがおすすめです。
4. ボタン操作とローディング管理
実際のアプリでは、ボタンを押してデータを取得することも多いです。そのときも同じようにローディング状態を管理します。ボタンを押した直後は「読み込み中...」を表示し、終わったら結果を出します。
import React, { useState } from "react";
import axios from "axios";
function FetchButton() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(false);
const fetchData = () => {
setLoading(true);
axios.get("https://jsonplaceholder.typicode.com/posts/1")
.then(res => setData(res.data))
.catch(() => setData({ title: "エラーが発生しました" }))
.finally(() => setLoading(false));
};
return (
<div>
<button onClick={fetchData} disabled={loading}>
{loading ? "読み込み中..." : "データを取得"}
</button>
{data && <div>{data.title}</div>}
</div>
);
}
export default FetchButton;
5. ローディング中のUIを工夫する
単純に「読み込み中...」と表示するだけでもよいですが、ユーザー体験を向上させるために以下の工夫もよく使われます。
- スピナー(ぐるぐる回るアイコン)を表示する
- スケルトンスクリーン(灰色の枠を表示して仮のUIを見せる)
- ボタンを無効化して二重クリックを防ぐ
これにより、アプリが「固まっている」のではなく「処理中」であることが直感的に伝わります。
6. 実務での注意点
実際の開発でAxiosのローディング管理を行うときは、以下の点に注意するとよいです。
- 複数のリクエストが同時に走る場合、それぞれのローディング状態を個別に管理する
- 大きなアプリではReduxやReact Queryを使って共通的にローディング状態を扱う
- ローディングが長引く場合は「しばらくお待ちください」などユーザーが安心できる工夫をする
こうした工夫を積み重ねることで、使いやすく信頼できるReactアプリを作れるようになります。
まとめ
ReactとAxiosにおけるローディング状態管理の振り返り
この記事では、ReactでAxiosを使って非同期通信を行う際に欠かせない「ローディング状態の管理」について、 初心者の方にも理解しやすい形で順を追って解説してきました。 非同期通信は、データの取得や送信に時間がかかる処理であり、その間に何も表示されていないと、 ユーザーは「画面が止まった」「操作できない」と感じてしまいます。 その不安を取り除くために重要なのが、ローディング状態を正しく管理し、今どんな状況なのかを画面上で伝えることです。
ReactではuseStateを使ってローディング用の状態を用意し、
通信の開始時にtrue、終了時にfalseへ切り替えることで、
シンプルかつ分かりやすくローディング管理ができます。
特にAxiosのfinallyを使うことで、通信が成功しても失敗しても必ずローディングを終了できるため、
「読み込み中のまま止まる」といったトラブルを防ぐことができます。
また、ボタン操作と組み合わせることで、ユーザーが操作した結果として通信が始まったことを明確に伝えられます。 読み込み中はボタンを無効化したり、文言を切り替えたりすることで、 二重クリックを防ぎつつ、現在の状態を直感的に理解してもらえるようになります。 こうした細かい配慮の積み重ねが、使いやすいReactアプリにつながります。
ローディング管理を意識したシンプルなサンプル構成
import React, { useState } from "react";
import axios from "axios";
function SimpleLoadingSample() {
const [message, setMessage] = useState("");
const [loading, setLoading] = useState(false);
const fetchData = () => {
setLoading(true);
axios.get("https://jsonplaceholder.typicode.com/posts/1")
.then(res => setMessage(res.data.title))
.catch(() => setMessage("データの取得に失敗しました"))
.finally(() => setLoading(false));
};
return (
<div>
<button onClick={fetchData} disabled={loading}>
{loading ? "読み込み中..." : "データ取得"}
</button>
{message && <p>{message}</p>}
</div>
);
}
export default SimpleLoadingSample;
このような構成にしておくことで、ローディング状態・データ表示・エラー時の表示を ひとつの流れとして整理できます。 初心者のうちは難しく考えず、「通信が始まったらローディングを表示し、終わったら必ず消す」 という基本をしっかり身につけることが大切です。
生徒:「ローディング状態を入れるだけで、画面の印象が全然変わりますね。」
先生:「そうですね。ユーザーは処理の中身よりも、今何が起きているかを知りたいんです。」
生徒:「finallyを使えば、失敗してもローディングが止まるのが安心です。」
先生:「そこが重要なポイントです。実務では、この書き忘れが原因の不具合もよくあります。」
生徒:「ボタンを無効化するのも、ユーザーのためなんですね。」
先生:「はい。操作できない理由が分かるだけで、使いやすさは大きく向上します。」
生徒:「これからは、非同期処理には必ずローディングをセットで考えます。」
先生:「その意識があれば、Reactでの非同期通信は確実にレベルアップしますよ。」