Vue.jsでAPIからデータを取得する場合、非同期処理のステータス(loading / error / success)を適切に管理することが重要です。これにより、ユーザーにとってわかりやすいUIを提供しつつ、コードの再利用性や保守性も向上します。
本記事では、Vue 3のComposition APIを活用した非同期状態管理の実装パターンを紹介します。
基本的な状態管理構成
まず、非同期処理には通常以下の3つの状態が必要です:
- loading:API処理中かどうか
- error:エラーが発生したかどうか
- data:取得したデータ
これらを一元的に扱うために、ref
とtry-catch-finally
構文を用いた実装が基本となります。
import { ref } from 'vue';
export function useFetch(url) {
const data = ref(null);
const error = ref(null);
const loading = ref(false);
const fetchData = async () => {
loading.value = true;
error.value = null;
try {
const res = await fetch(url);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
data.value = await res.json();
} catch (err) {
error.value = err.message;
} finally {
loading.value = false;
}
};
return { data, error, loading, fetchData };
}
このようにComposable関数useFetch
として定義すれば、複数のコンポーネントで再利用できます。
実際のコンポーネントでの使用例
<script setup>
import { onMounted } from 'vue';
import { useFetch } from './composables/useFetch';
const { data, error, loading, fetchData } = useFetch('https://api.example.com/users');
onMounted(() => {
fetchData();
});
</script>
<template>
<div v-if="loading">読み込み中...</div>
<div v-else-if="error">エラー発生: {{ error }}</div>
<ul v-else>
<li v-for="user in data" :key="user.id">{{ user.name }}</li>
</ul>
</template>
このように状態に応じた表示を切り替えることで、ユーザーにとって直感的なUIが実現できます。
状態管理をモジュール化する利点
- 全API呼び出しに共通のロジックを適用できる
- ローディング状態やエラーハンドリングのコードが一貫する
- ユニットテストやMockの導入も容易になる
特に大規模アプリケーションでは、APIごとに状態変数をバラバラに管理するとメンテナンス性が低下するため、Composable関数による共通化が効果的です。
拡張例:ローディング重複の防止・再試行・キャンセル
以下のような拡張も可能です:
- 二重fetch防止のための
isFetching
フラグ - 自動リトライや指数バックオフ
- AbortControllerでキャンセル対応
const controller = new AbortController();
const signal = controller.signal;
const res = await fetch(url, { signal });
まとめ
非同期APIの状態管理において、loading / error / successの3ステータスを共通パターンで管理することは、開発効率と保守性を大きく高めます。
Vue 3 の Composition API と Composable 関数を組み合わせることで、状態管理をモジュール化し、アプリケーション全体で一貫した実装を実現できます。
ぜひ本記事のパターンをプロジェクトに応用して、UIの信頼性と開発体験の向上を図ってみてください。