Programming Journal

学習したことの整理用です。

【Vue.js】【Vuex】Storeを分割してモジュール化し、namespacedを登録する

実装したいこと

Vuexのストアをモジュールに分割して読み込みたい。
アプリケーションの規模が大きくなると、ストアの規模も大きくなり管理が困難になるため、ストアを適切に分割し管理したい。

モジュール | Vuex

モジュールを読み込む

store/index.jsにまとめていたstorestore/modues/task.jsに切り出す。

import Vue from 'vue'
import Vuex from 'vuex'
import tasks from './modules/task' // 分割したモジュールを呼び出す

Vue.use(Vuex)

export default new Vuex.Store({
  modules: {
    tasks // 追加
  }
})
import axios from '../../plugins/axios'

// taskモジュールを定義
export default { // 注意(後述)
  namespaced: true,  // 名前空間 'namespaced'なことに注意
  state: {
    tasks: [],
  },

  getters: {
    tasks: (state) => state.tasks
  },

  actions: {
    fetchTasks({ commit }) {
      axios.get("tasks")
        .then(response => { commit('loadTasks', response.data)
        })
        .catch(error => console.log(error.status));
    }
  }
}

エラー

2時間位溶かす。エラーの切り出しが下手で時間がかかってしまいます…
今見たら、エラー文にちゃんと原因が書いてあった。すぐgoogleで調べる癖は悪なので反省

名前空間をつけたモジュールが読み込めない…

f:id:Study-Diary:20201117111905p:plain
エラー画面
f:id:Study-Diary:20201117111843p:plain
エラー画面

vuex.esm.js:345 Uncaught TypeError: Cannot read property 'getters' of undefined

ERROR in ./app/javascript/store/index.js 8:10-14
"export 'default' (imported as 'task') was not found in '../store/modules/task'
// taskモジュールを名前付きで定義
export const task = {
  namespaced: true,

名前付きのexportnamed exportでなく、export defaultにしたら直った

参考
https://stackoverflow.com/questions/58511705/uncaught-typeerror-cannot-set-property-render-of-undefined

namespaced: trueタイポ
namespace: trueにしてた…

呼び出し側

<script>
import { createNamespacedHelpers } from 'vuex' // 追加

const { mapActions, mapGetters } = createNamespacedHelpers('tasks') // 追加

export default {
  computed: {
    ...mapGetters(["tasks"])
  },

  created() {
    this.fetchTasks();
  },

  methods: {
    ...mapActions([
      "fetchTasks"
    ])
  }
}
</script>

createNamespacedHelpersというヘルパーを使ったら簡単にできました。
これを使わない場合は、第一引数にモジュール名を渡せばOK

 ...mapGetters( "tasks",["tasks"])

...mapActions("tasks",[
      "fetchTasks"
    ])

スタイルガイド

スタイルガイド — Vue.js