14
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Vuex/Nuxt] storeをmodule化したときに[vuex] unknown action typeが出たときの対処法およびデバッグ法

Last updated at Posted at 2020-03-20

きっかけ

今までクラシックモードで書いていたstoreをモジュールモードで書くことにしました。
index.jsの中でarticle.jsというファイルをmoduleとしてimportしたあと、
componentでactionを実行しようとしたら[vuex] unknown action type
というエラーが出たので、その対処法およびデバッグ法をご紹介します。

ファイル

store/index.js
import Vuex from "vuex";
import articles from "./modules/articles"

const store = () => new Vuex.Store({
  modules: {
    articles
  }
})

export default store
store/modules/article.js
const namespaced = true

const state = () => ({
  articles: []
})

const mutations = () => ({
  SET_ARTICLES(state, articles) {
    state.articles = articles
  }
})

const actions = () => ({
  setArticles(vuexContext, articles) {
    vuexContext.commit("SET_ARTICLES", articles)
  },
})

const getters = () => ({
  getArticles(state) {
    return state.articles
  }
})

export default {
  namespaced,
  state,
  mutations,
  actions,
  getters
}
pages/index.vue
<template>
  <div>
    <Header />
    <ArticleList :articles="articles" />
  </div>
</template>

<script>
import Header from '@/components/molecules/Header.vue'
import ArticleList from '@/components/organisms/ArticleList.vue'
import { mapGetters } from 'vuex'

export default {
  name: 'TopPage',
  components: {
    Header,
    ArticleList
  },
  async fetch({store, $axios}) {
    await $axios.$get("http://localhost:3000/api/v1/articles")
      .then((data) => {
        store.dispatch("articles/setArticles", data)
      })
      .catch(e => {
        console.log(e)
      })
  },
  computed: {
    ...mapGetters({
      articles: "articles/getArticles"
    }
  }
}
</script>

この状態でサーバにアクセスしたところ、
[vuex] unknown action type 'setArticles' undefined
が出てしまいました。
pages/index.vueのfetchのthen内部のdispatchが呼び出せていないようです。
しかし、moduleの設定などは確認したところすべて合っていました。

自分がしたこと

そもそも、setArticlesが読み込めていないということは、
1. article.jsでのsetArticlesメソッドの設定がおかしく読み込めていない
2. そもそもarticle.jsをmoduleとして読み込めていない
可能性があるので、まずは2番から確認していくことにしました。

「2. そもそもarticle.jsをmoduleとして読み込めていない」について

これは、axiosでdataを取得したあとのthenで一度 contextを確認してみればいいと感じました。

pages/index.vueのthenにconsole.logをはさみます。
※このcontextはnuxtContextです

pages/index.vue
<script>
...
  async fetch(context) {
    await $axios.$get("http://localhost:3000/api/v1/articles")
      .then((data) => {
        console.log(context.store.state) // ここです
        store.dispatch("articles/setArticles", data)
      })
      .catch(e => {
        console.log(e)
      })
...
</script>

結果としては、以下のオブジェクトが返ってきました。

{ article: { articles: [] } }

なので、article.js自体はmoduleとして正しく読み込まれている ことがわかりました。

1. article.jsでのsetArticlesメソッドの設定がおかしく読み込めていない」について

となれば、あとはsetArticlesメソッドの部分を確認します。

これ、もう結論を言ってしまうのですがなぜ動かなかったのかというと、
article.jsの各定数(変数)をObjectではなくfunctionとして定義していたからです。

functionとして定義(動かなかった)

store/modules/article.js
const namespaced = true

const state = () => ({
  articles: []
})

const mutations = () => ({
  SET_ARTICLES(state, articles) {
    state.articles = articles
  }
})

const actions = () => ({
  setArticles(vuexContext, articles) {
    vuexContext.commit("SET_ARTICLES", articles)
  },
})

const getters = () => ({
  getArticles(state) {
    return state.articles
  }
})

export default {
  namespaced,
  state,
  mutations,
  actions,
  getters
}

Objectとして定義(動いた)

store/modules/article.js
const namespaced = true

const state = {
  articles: []
}

const mutations = {
  SET_ARTICLES(state, articles) {
    state.articles = articles
  }
}

const actions = {
  setArticles(vuexContext, articles) {
    vuexContext.commit("SET_ARTICLES", articles)
  },
}

const getters = {
  getArticles(state) {
    return state.articles
  }
}

export default {
  namespaced,
  state,
  mutations,
  actions,
  getters
}

actions, mutationsのデバッグについて

一番最初に確認した2.のケースではstateが正常に読み込まれていたので、
stateに関してはアロー関数式で表現しても問題ないように思いました。

が、actionsとmutations、gettersに関してはアロー関数式で定義するとunknown action typeが出てしまいます。

その際に、「どのようにしてactionsとmutations, gettersが正しく読み込まれているのかを知るのか」がわかりませんでしたが、
contextを確認した際にその確認方法がわかった気がしましたので、ここに載せておきます。

先程2.を確認した際、context.storeを確認しましたが、
このstoreの中にstateがあるならactionsやmutations, gettersもあるはず。
と考え、確認してみました。以下が確認結果となります(長いので大部分省略しています)

console.log(context.store)
<ref *5> Store {
  _committing: false,
  // 3行目------
  _actions: [Object: null prototype] {},
  _actionSubscribers: [],
  _mutations: [Object: null prototype] {},
  _wrappedGetters: [Object: null prototype] {},
  // ----------
  _modules: ModuleCollection {
    root: Module {
      runtime: false,
      _children: [Object: null prototype],
      _rawModule: [Object],
      state: [Object],
      context: [Object]
    }
  },
  // 下から9行目
  _modulesNamespaceMap: [Object: null prototype] {
    'articles/': Module {
      runtime: false,
      _children: [Object: null prototype] {},
      _rawModule: [Object],`
      state: [Object],
      context: [Object]
    }
  },

下から9行目、 _modulesNamespaceMapのところに'articles/': Moduleとあるので、articles.jsが正しくmoduleとして読み込まれている、ということでしょう。

そして、3行目から下4行を見ると、_actions, _mutations, _wrappedGettersがあり、いずれも [Object: null prototype] {},となっています。
これは2.で確認した失敗のケースなので、actions, mutations, gettersともに登録されておらず{}となっているのでしょう。
おそらくここがactions, mutations, wrappedGettersのstoreだろうという推測のもと、それらをfunctionからobject表記に戻して確認してみると、

console.log(context.store)
<ref *5> Store {
  _committing: false,
  _actions: [Object: null prototype] {
    'articles/setArticles': [ [Function: wrappedActionHandler] ]
  },
  _actionSubscribers: [],
  _mutations: [Object: null prototype] {
    'articles/SET_ARTICLES': [ [Function: wrappedMutationHandler] ]
  },
  _wrappedGetters: [Object: null prototype] {
    'articles/getArticles': [Function: wrappedGetter]
  }

となり、やはり_actions, _mutations, _wrappedGettersがactions, mutations, gettersのstoreであることが実際にわかると思います。

まあstoreの中に入っているので当然といえば当然ですが、これを知っているだけでもデバッグは捗るような気がしています。

まとめ

1. unknown action typeが出る場合は、state, actions, mutations, gettersの定義を確認してみよう
→ functionではなくobjectとして登録するのが正解
2. actions, mutations, gettersが読み込まれているかを確認するときは、nuxtContextのstore内部の
_actions, _mutations, _wrappedGetters`の中身を確認してみよう

14
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?