[Vuex]do not mutate vuex store state outside mutation handlers.の解決方法
Vuexを最近使いはじめ、
Error: [vuex] do not mutate vuex store state outside mutation handlers.
[Vue warn]: Error in callback for watcher "function () { return this.data.$$state }":
Error: [vuex] do not mutate vuex store state outside mutation handlers."
こんなエラーが出ました。
色々と調べていると、『初心者がよく躓くエラー』だそうです。(精進します。。)
TL;DR
let hoge = [] // 操作したいオブジェクト配列
// this.vuex.objArr がvuexで管理されている変数
hoge = JSON.parse(JSON.stringify(this.vuex.objArr))
JSON.parse(JSON.stringify(obj))を使ってオブジェクトをコピーしましょう。
もしこれを使わずに普通に代入すると、『shallow copy』(浅いコピー)になってしまい参照元はvuexの方を見てしまうためエラーになります。
これを回避するために、上記の方法で『deep copy』(深いコピー)を使うというわけですね。
これはどんなエラー?
Error: [vuex]do not mutate vuex store state outside mutation handlers.
vuexの変数なのに、直接変更しようとしたでしょ?mutation機能使って変更して!
って怒られています。
文字通り、vuexで管理している変数を直接書き換えようとした時に出るエラーです。
しかし今回私は、一回ローカル変数に代入してそいつを書き換えている。
直接vuexの変数などいじっていない。
↓のように、ローカル変数にオブジェクトの配列をコピーして使っているのだ。
let hoge = [] // 操作したいオブジェクト配列
// this.vuex.objArr がvuexで管理されている変数
hoge = this.vuex.objArr // 代入
hoge[0].name = "山田花子" // コピーしたローカルの値を変更
// ここでエラー Error: [vuex]do not mutate vuex store...
…
…………
オブジェクトをコピーする、ここがキモだったのだ!
エラーになる原理
vuexでオブジェクト要素を扱うときの原理です。
shallow copy(浅いコピー)
オブジェクトをコピーするときに、安直にそのまま代入してしまうと『shallow copy』(浅いコピー)になってしまいます。
shallow copyとは何かというと、コピー元とコピー先両方が同じメモリを参照している状態のことを言います。
今回のパターンでこれの何がマズいかというと、コピー元はvuexでメモリに保存されています。
これを浅いコピーして書き換えたとしても、vuexで管理されたメモリを直接書き換えようとしているのでmutationを使ってくださいと言われてしまう訳です。
deep copy(深いコピー)
では、同じメモリを参照しないようにすれば解決できそうです。
そこでオブジェクトだけでなく、メモリ上のデータも他の部分にコピーしてしまえば良いじゃないかというのが『deep copy(深いコピー)』です。
今回のパターンでは、メモリ上のデータもそっくりそのまま別のところへコピーしているのでvuexの管理下から逃れることができます。
これを使うケースはというと、入力フォームをvuexで持っていて、保存を押した時にstateに保存するケースです。
input要素に直接vuexのプロパティをバインドしてしまうと、更新するときなど何かと不便だったりします。
shallow copyとdeep copyの詳しい違い
詳しい違いについては、こちらの記事にまとめていますので、お時間のある方はぜひ読んでみてください。
解決方法
JSON.parse(JSON.stringify(obj))を使う
let hoge = [] // 操作したいオブジェクト配列
// this.vuex.objArr がvuexで管理されている変数
hoge = JSON.parse(JSON.stringify(this.vuex.objArr))
vuexでオブジェクト要素を扱う時は、JSON.parse(JSON.stringify(obj))を使って代入をしましょう。
そうすることでdeep copyとなり、コピー先はコピー元のメモリを参照しないのでvuexの支配下から逃れ直接編集することができます。

zawa1205
webフロントエンドエンジニア