🔧 6-3. Vuex アクションを使った非同期処理のリファクタリング
✅ 要点まとめ
- 非同期処理(API 呼び出しなど)を Vuex の actions にまとめる と再利用しやすい。
- コンポーネント内をシンプルに保ち、ロジックを Vuex 側に移す。
- Composition API では
store.dispatch('actionName')
でアクションを実行。
- エラーハンドリングもアクション内でまとめる ことでスッキリ。
🟢 基本パターン(非同期処理をアクションに移す)
【Vuex ストア側の定義】
// ファイル名: store/index.ts
import { createStore } from 'vuex';
export interface State {
message: string;
}
export const store = createStore<State>({
state: {
message: '',
},
mutations: {
setMessage(state, payload: string) {
state.message = payload;
},
},
actions: {
async fetchMessage({ commit }) {
try {
const response = await fetch('<https://api.example.com/data>');
if (!response.ok) throw new Error('データ取得失敗');
const data = await response.json();
commit('setMessage', data.message);
} catch (error) {
console.error('アクション内エラー:', error);
commit('setMessage', '取得失敗');
}
},
},
});
🟡 コンポーネント側(Composition API)
<!-- ファイル名: MessageComponent.vue -->
<template>
<div>
<p>{{ message }}</p>
<button @click="loadMessage">データ取得</button>
</div>
</template>
<script setup lang="ts">
import { useStore } from '../store/useStore';
import { computed } from 'vue';
// ストア取得
const store = useStore();
// state から message を取得
const message = computed(() => store.state.message);
// アクションを呼び出す関数
const loadMessage = () => {
store.dispatch('fetchMessage');
};
</script>
🟣 メリット(なぜアクションに非同期処理を移すのか)
コンポーネント内 |
Vuex アクションにリファクタリング後 |
API 処理が入り乱れてコードが汚い |
ロジックを Vuex に集約 → スッキリ |
再利用が難しい |
他のコンポーネントでも同じアクションを使える |
エラーハンドリングがバラバラ |
アクション内にまとめられる |
🟢 応用:パラメータ付きアクション
// store/index.ts のアクション
actions: {
async fetchUser({ commit }, userId: string) {
try {
const response = await fetch(`https://api.example.com/users/${userId}`);
const data = await response.json();
commit('setMessage', `User: ${data.username}`);
} catch (error) {
commit('setMessage', 'ユーザー取得失敗');
}
},
}
<!-- 呼び出し側 -->
const loadUser = (id: string) => {
store.dispatch('fetchUser', id);
};