Vuex.store.stateの値をmutationsで変更しようとしたら、mutationsを使わずに値を変えるなと怒られた

タイトルの日本語がおかしい気もしますが、タイトル通りの状況で困ったので記録に残そうと思います。


状況説明

 Nuxt.jsでVueコンポーネントのinputフォームから入力された値を使って、Vuex.store に登録した stateの値を書き換える、シンプルな機能を実装しようとしたところ、下記のエラーがでて、動作が止まってしまいました。

null: Error: [vuex] Do not mutate vuex store state outside mutation handlers.

null: Object {statusCode: <accessor>, message: <accessor>, __ob__: Observer}

コンポーネントはこちら


inputComp.vue

<template>

<div>
<input text="Number" @input="inputedNum" />
<button @click="updateStore" />
</div>
</template>
<script>
export default {
prop: ['id', 'key'],
data() {
inputedNum: 0
},
methods: {
updateStore() {
$store.commit('updateStore', {
id: this.id,
key: this.key,
value: this.inputedNum
})
},
},
}
</script>

store/index.js はこちら


store/index.js

export const state = () =>({

...
data: [
{ id: 0, piyo: 0, piyopiyo: 0 ... },
{ id: 1, piyo: 0, piyopiyo: 0 ... },
{ id: 2, piyo: 0, piyopiyo: 0 ... },
...
],
})

export const mutations = {
updateStore(state, payload) {
state.data.forEach((el, index) => {
if (el.id === payload._id) {
data[index][payload.key] = payload.value
}
})
},
}


この時点で、「あっ…(察し)」となった方も多いかと思います。


原因

 結局のところ、数値の値をもつ連想配列のvalueに対して文字列を代入していたことがエラーの原因でした。

inputされた値は文字列として扱われている(当然といえば当然)ので、これを数値に変換してあげる必要がありました。

じゃあmutations外から値を変えるなとか言うなよ…


学び


  • TypeScriptを使え

  • Vue DevTools をもっと上手に使え

実際のコードはもうちょっといろいろあるので、他の場所で勝手に値が変わってしまってるのかと思って、

いろいろ探し回っていたら2時間が経っていました。

そしてもう一度Vue devToolsをつかってVuex.store.stateにどんな値が入っているのかを確認したら、入力値が文字列になっていることに気づけました。。。

Vue DevTools は早く使いこなせるようになったほうがいいです。


そして

そもそも迷う原因となったVuexのメッセージがどういう経路で出ているのか実装を追ってみたいなと思いました。適切なメッセージが出せるのであれば、ぼくみたいな初心者にももうちょっと優しくなれるかもしれませんし。みつけたらプルリクのチャンスかも。