Vuex

Vue 2 の既存アプリケーションで共有 state を扱う Vuex の基本構造と保守の視点を学ぶ。

Vuex は Vue 向けの集中型 state 管理パターンとライブラリです。Vue 2 の既存アプリケーションでは、認証情報、カート、画面横断の設定などを Vuex Store で管理していることが多くあります。

新規の Vue プロジェクトでは Pinia がよく選ばれますが、Vuex を理解すると既存コードを安全に読めます。重要なのは API 名を覚えることより、state がどの経路で変わるかを追えることです。

Vuex の一方向の流れ

Vuex は主に state、getters、mutations、actions で構成されます。

コンポーネント → dispatch → action → commit → mutation → state → 画面
  • state: アプリケーションが保持する事実
  • getters: state から導く値
  • mutations: state を同期的に変更する唯一の場所
  • actions: 非同期処理や複数 mutation の調整を担当する場所

この分離により、Devtools でどの mutation が state を変えたかを追跡しやすくなります。

Store の基本例

次はカウンターを持つ最小の Store です。通信などの非同期処理は action に置き、mutation は state の変更だけを扱います。

export default new Vuex.Store({
  state: {
    count: 0,
  },
  getters: {
    doubleCount: (state) => state.count * 2,
  },
  mutations: {
    increment(state) {
      state.count += 1
    },
  },
  actions: {
    async refreshCount({ commit }) {
      const count = await fetchCount()
      commit('setCount', count)
    },
  },
})

例では refreshCount が非同期処理を担当し、結果を mutation 経由で state に反映します。mutation の外側で state を直接変更すると、変更履歴を追いにくくなります。

コンポーネントから使う

Options API のコンポーネントでは、this.$store.state、this.$store.getters、this.$store.commit、this.$store.dispatch を使えます。規模が大きくなると、mapState や mapActions などのヘルパーで記述を整理します。

export default {
  computed: {
    count() {
      return this.$store.state.count
    },
  },
  methods: {
    increment() {
      this.$store.commit('increment')
    },
  },
}

コンポーネントが Store の内部構造を多く知りすぎないよう、意味を持つ action や getter を用意します。たとえば commit('SET_USER', user) を画面中へ散らすより、認証に関する action に集約した方が変更しやすくなります。

Module で責務を分ける

一つの root Store にすべてを置くと、state と mutation の名前が増え続けます。auth、cart、notifications のように責務ごとの module に分け、必要に応じて namespace を使います。

ただし module を増やすほど、他 module への依存や root state へのアクセスも複雑になります。画面構造ではなく、データの所有者と変更理由を基準に分割します。

Vuex を保守・移行するときの判断

Vuex があるプロジェクトでは、まず mutation と action をたどり、state の正本を確認します。いきなり Pinia へ書き換えるより、Store の責務、非同期処理、テスト、Devtools の利用状況を把握する方が安全です。

新規機能を追加する際は、プロジェクトが Vue 2 を継続保守するのか、Vue 3 と Pinia へ移行する計画があるのかを確認します。Vuex の知識はレガシーコードを読み解く基礎として、Pinia の知識は新しい Store 設計の選択肢として役立ちます。

Sources