・外部APIを取得する際の注意点
こんにちは、フロントエンドエンジニアのてりーです。
React + TypeScriptを5年以上使い続け、派遣 → フリーランス → メガベンチャーとキャリアを積んできました。
詳しいキャリアや学習ロードマップについてはこちらからどうぞ!
👉 本記事ではReact Hooksの中でも特に重要なuseEffect
に焦点を当てて解説します!
1. useEffectとは
useEffect
は、コンポーネントを外部システムと同期させるための React フックです。
useEffectの特徴は関数の実行タイミングを任意で設定できる事です!
関数コンポーネントの処理タイミングに関係なく、好きなタイミングで実行出来るので、「副作用フック」と呼ばれたりもします。
主な用途
- データ取得(API通信)
- DOMの操作
- サブスクリプション(イベントリスナーの設定など)
例: ページが読み込まれたときにuseEffectを実行
import { useEffect } from 'react';
useEffect(() => {
console.log('コンポーネントがマウントされました');
}, []);
依存配列(Dependency Array)
- 空配列
[]
: マウント時のみ実行。 - 変数を指定
[state]
: 変数が更新されるたびに実行。
ReactとTypeScriptを基礎から習得したい方は、こちらもチェック!
👉【2025年】未経験から即戦力へ!React+TypeScriptの学習ロードマップ
2. useEffectを使ったAPI通信の基本
2.1 API通信の基本形
useEffect
を使ってAPIからデータを取得する基本例を紹介します。
import { useState, useEffect } from 'react';
function App() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/posts/1')
.then((data) => setData(data))
.catch((error) => console.error('Error fetching data:', error));
}, []);
return (
<div>
{data ? <h1>{data.title}</h1> : <p>Loading...</p>}
</div>
);
}
2.2 解説
1. 初回マウント時にAPIを実行
useEffectの依存配列を[]とする事で、コンポーネントが初回にマウントされた時のみ実行され、複数回APIを叩く事を防いでいます!
2. 取得したデータをuseStateで管理
fetch('https://jsonplaceholder.typicode.com/posts/1')
.then((data) => setData(data))
.catch((error) => console.error('Error fetching data:', error));
fetch関数で取得したdataはsetDataを用いてstateに反映しています!
3. エラーハンドリングで安全性を担保
.catch((error) => console.error('Error fetching data:', error));
API通信でエラーが出た際は、console.errorでエラー内容を通知しています。
フロントエンドのAPI知識に不安がある方は、こちらもチェック!
👉フロントエンドエンジニアのためのHTTP・APIガイド
3. useEffectの実装でよくあるエラーとその対処法
次にuseEffectをよくぶち当たるエラーを見ていきましょう!
3.1 無限ループ: 依存配列を指定し忘れた場合
useEffect(() => {
fetchData();
}); // ⚠️ 無限ループの原因
解決策
useEffect(() => {
fetchData();
}, []); // ✅ 依存配列を追加
3.2 クリーンアップ漏れ: API通信が中断されずエラーになる
useEffect(() => {
const controller = new AbortController();
fetch('https://api.example.com/data', { signal: controller.signal });
return () => controller.abort();
}, []);
解決策
useEffect内で行われたAPI通信は、コンポーネントがアンマウント(画面から削除)された後も通信が継続してしまうことがあります。
これにより、以下のような問題が発生します。
- エラー発生: コンポーネントが既に存在しないのに、通信結果を
setState
しようとする。 - メモリリーク: 不要なAPI通信が継続され、メモリリソースが無駄に消費される。
以下のコードのようにAPI通信に対するエラーハンドリングを適切に行いましょう!
useEffect(() => {
const controller = new AbortController();
async function fetchData() {
try {
// API通信開始
const response = await fetch('https://api.example.com/data', {
signal: controller.signal,
});
// ステータスコードチェック
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
// データ取得
const result = await response.json();
console.log('取得したデータ:', result);
} catch (err) {
if (err.name === 'AbortError') {
console.warn('API通信が中断されました:', err.message);
} else if (err.name === 'TypeError') {
console.error('ネットワークエラーが発生しました:', err.message);
} else {
console.error('API通信中に予期しないエラーが発生しました:', err.message);
}
} finally {
console.log('API通信が完了または中断されました');
}
}
fetchData();
return () => {
console.log('API通信を中断します');
controller.abort();
};
}, []);
実践的なプロダクトを作りながらReactを学びたい方へ!
👉 【React+TypeScript】Netflixのクローンを作るチュートリアル
👉【 React Hooks入門】useStateで買い物リストを作るチュートリアル
4. 最新トレンド: AxiosやReact Queryを使ったAPI通信
Reactを使う現場でのAPI通信の方法も様々な選択肢が出てきています!
今回はその中で有力なAxiosとReact Queryを使った例を見ていきましょう。
4.1 Axiosを使ったAPI通信
Axiosはfetch
に比べてシンプルかつ機能豊富なHTTPクライアントライブラリです。
特に、エラーハンドリングやリクエスト・レスポンスのインターセプター機能が便利です。
Axiosを使うメリット
-
デフォルト設定が簡単
- ベースURLやヘッダーを設定しやすい
-
エラーハンドリングがわかりやすい
response.status
やエラーメッセージが明確
-
リクエスト・レスポンスのインターセプター
- リクエスト前後に共通処理を挟める
Axiosを使ったAPIの通信例
import axios from 'axios';
import { useEffect, useState } from 'react';
function App() {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const controller = new AbortController();
async function fetchData() {
try {
setLoading(true);
// AxiosでAPIリクエストを送信
const response = await axios.get('https://api.example.com/data', {
signal: controller.signal, // 中断信号を送る
});
setData(response.data);
} catch (err) {
if (axios.isCancel(err)) {
console.warn('API通信が中断されました:', err.message);
} else {
console.error('API通信エラー:', err.message);
setError(err);
}
} finally {
setLoading(false);
}
}
fetchData();
return () => {
console.log('API通信を中断します');
controller.abort();
};
}, []);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<div>
{data ? (
<pre>{JSON.stringify(data, null, 2)}</pre>
) : (
<p>No data available</p>
)}
</div>
);
}
export default App;
Axiosのインターセプターの例
import axios from 'axios';
axios.interceptors.request.use(
(config) => {
console.log('リクエスト送信:', config.url);
return config;
},
(error) => {
return Promise.reject(error);
}
);
axios.interceptors.response.use(
(response) => {
console.log('レスポンス受信:', response.status);
return response;
},
(error) => {
console.error('エラー:', error.message);
return Promise.reject(error);
}
);
4.2 React Queryを使ったAPI通信
React QueryはReactでデータフェッチやキャッシュ管理、エラーハンドリングを効率的に行えるライブラリです。
サーバー状態をシンプルに管理し、再レンダリングを最小化できます。
最近は名称が変わってtanstackQueryになりましたね!
TanStack Query (FKA React Query) is often described as the m…
React Queryを使うメリット
-
自動キャッシュ管理
- データがキャッシュされ、不要なリクエストを減少。
-
自動再フェッチ
- フォーカスが戻ったとき、または特定の条件でデータを自動更新。
-
エラーハンドリング
- エラー情報を簡単に取得してUIで表示可能。
-
データの状態管理
isLoading
、error
、data
などの状態が明確。
React Queryの基本的なAPI通信
import { useQuery, QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
<DataFetchingComponent />
</QueryClientProvider>
);
}
function DataFetchingComponent() {
const { data, error, isLoading } = useQuery({
queryKey: ['data'],
queryFn: async () => {
const response = await fetch('https://api.example.com/data');
if (!response.ok) {
throw new Error('データ取得に失敗しました');
}
return response.json();
},
});
if (isLoading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<div>
<h1>データ取得成功!</h1>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}
export default App;
React Queryの自動再フェッチ例
const { data, error, isLoading } = useQuery({
queryKey: ['data'],
queryFn: async () => {
const response = await fetch('https://api.example.com/data');
return response.json();
},
refetchOnWindowFocus: true, // フォーカス時に自動再フェッチ
});<br />
4.3 Axios vs React Query
説明したAxiosとReact Queryを比較してみましょう。
機能 | Axios | React Query |
---|---|---|
データ取得 | ✅ 簡単 | ✅ 簡単 |
キャッシュ | ❌ なし | ✅ 自動管理 |
自動再フェッチ | ❌ 手動 | ✅ 自動 |
状態管理 | ❌ 外部管理要 | ✅ 内部で自動管理 |
エラーハンドリング | ✅ 優秀 | ✅ 優秀 |
おすすめ用途 | 個別のAPI通信に最適 | アプリ全体のAPI管理に最適 |
こんな人におすすめ | シンプルなAPIリクエストを使いたい人 | 複雑なデータ状態を管理したい人 |
まとめると
- Axios: シンプルなAPIリクエストとエラーハンドリング向け
- React Query: データのキャッシュ、自動再フェッチ、大規模アプリケーション向け
と言った感じです!
Reactを使った転職活動をしたい方へ!
5. まとめ: ReactでAPI通信を効率的に行うために
ReactでAPI通信を効率的かつ安全に行うためには、以下のポイントを意識することが重要です。
-
useEffectを適切に使う
- API通信は
useEffect
内で行い、依存配列(Dependency Array)を正しく設定する。 - 不要な再レンダリングを防ぐために、依存関係の管理を徹底する。
- API通信は
-
クリーンアップ関数で通信を管理
AbortController
を使用して、コンポーネントのアンマウント時にAPI通信を中断する。- メモリリークや不要なリクエストを防ぐため、クリーンアップ処理は必ず実装する。
-
AxiosやReact Queryを活用
- Axios: シンプルでエラーハンドリングがしやすいAPI通信ライブラリ。
- React Query: データのキャッシュ、自動再フェッチ、状態管理が得意なライブラリ。
- プロジェクトの規模や要件に合わせて使い分ける。
React関連の記事
👉【2025年】未経験から即戦力へ!React+TypeScriptの学習ロードマップ
👉 【React+TypeScript】Netflixのクローンを作るチュートリアル
👉【 React Hooks入門】useStateで買い物リストを作るチュートリアル
人気記事
👉 未経験の僕がメガベンチャーエンジニアになった軌跡
👉 エンジニア転職で年収アップを実現
👉【転職ドラフト指名の画像アリ】2年目で600万の指名を獲得した僕が考える技術自信ナシでも転職ドラフトを使った方が良い理由
👉フルリモート週2~3日からでも副業が出来るエージェント紹介