🔧 6-3. Vuex アクションを使った非同期処理のリファクタリング

✅ 要点まとめ


🟢 基本パターン(非同期処理をアクションに移す)

【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);
};