ReactのuseEffectでリトライ処理を実装する方法を初心者向けに解説
生徒
「先生、サーバーからデータを取ってくるときに失敗することがありますよね?そのときに自動で再試行、いわゆるリトライってできますか?」
先生
「とても大事な視点ですね。ネットワークは必ず安定しているわけではありませんから、Reactでリトライ処理を実装する方法を知っておくと安心です。」
生徒
「ReactのuseEffectを使ってリトライ処理ってどう書くんですか?」
先生
「では、useEffectと非同期処理を組み合わせて、リトライを実装する方法を順番に見ていきましょう。」
1. Reactでリトライ処理が必要な理由
Reactで非同期処理を行うとき、たとえばfetchを使ってAPIからデータを取得する場合、常に成功するとは限りません。通信環境が悪かったり、サーバー側が一時的にエラーを返すこともあります。そのようなときに「失敗したらもう一度試す」仕組みを入れておくと、ユーザー体験が向上します。
例えば、インターネットで動画を見ているときに一瞬止まっても、数秒後に自動で再生が復帰することがありますよね。それと同じように、Reactアプリでもリトライ機能をつけておくと便利です。
2. useEffectと非同期処理の基本
useEffectは、コンポーネントが表示されたときに実行したい処理を書く場所です。そこにasync/awaitを使ってAPI通信を行えば、画面に表示するデータを取得できます。ただし失敗する可能性もあるため、リトライ処理を組み込む必要が出てきます。
3. シンプルなリトライ処理の実装例
まずは、指定した回数だけ再試行するシンプルなリトライ処理を実装してみましょう。
import React, { useEffect, useState } from "react";
function App() {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
let isMounted = true;
async function fetchDataWithRetry(retries = 3, delay = 1000) {
for (let i = 0; i < retries; i++) {
try {
const res = await fetch("https://jsonplaceholder.typicode.com/posts/1");
if (!res.ok) throw new Error("サーバーエラー");
const json = await res.json();
if (isMounted) setData(json);
return;
} catch (err) {
if (i === retries - 1) {
if (isMounted) setError("データ取得に失敗しました");
} else {
await new Promise((resolve) => setTimeout(resolve, delay));
}
}
}
}
fetchDataWithRetry();
return () => {
isMounted = false;
};
}, []);
return (
<div>
<h1>記事タイトル</h1>
{error && <p style={{ color: "red" }}>{error}</p>}
{data ? <p>{data.title}</p> : <p>読み込み中...</p>}
</div>
);
}
export default App;
4. リトライ間隔を伸ばす「指数バックオフ」
毎回同じ間隔でリトライするのではなく、失敗するたびに待機時間を少しずつ長くする方法を「指数バックオフ」といいます。例えば最初は1秒待ち、次は2秒、その次は4秒といった具合です。これによりサーバーに負担をかけにくくなり、効率的に通信を再試行できます。
5. 初心者が覚えておきたいポイント
- useEffectの中で非同期処理をするときは失敗を前提に考える
- リトライ処理を入れることでユーザーに優しいアプリになる
- バックオフ(待機時間を伸ばす)を組み合わせるとさらに実践的
これらを理解すれば、初心者でも安定したReactアプリを作れるようになります。インターネットは常に完璧ではないので、「失敗したらもう一度」が自然にできるアプリ設計を意識しましょう。