Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vuex - Do not mutate vuex store state outside mutation handlers

Why do I get this error:

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

What does it mean?

It happens when I try to type in the edit input file.

pages/todos/index.vue

<template>   <ul>     <li v-for="todo in todos">       <input type="checkbox" :checked="todo.done" v-on:change="toggle(todo)">       <span :class="{ done: todo.done }">{{ todo.text }}</span>       <button class="destroy" v-on:click="remove(todo)">delete</button>        <input class="edit" type="text" v-model="todo.text" v-todo-focus="todo == editedTodo" @blur="doneEdit(todo)" @keyup.enter="doneEdit(todo)" @keyup.esc="cancelEdit(todo)">      </li>     <li><input placeholder="What needs to be done?" autofocus v-model="todo" v-on:keyup.enter="add"></li>   </ul> </template>  <script> import { mapMutations } from 'vuex'  export default {   data () {     return {       todo: '',       editedTodo: null     }   },   head () {     return {       title: this.$route.params.slug || 'all',       titleTemplate: 'Nuxt TodoMVC : %s todos'     }   },   fetch ({ store }) {     store.commit('todos/add', 'Hello World')   },   computed: {     todos () {       // console.log(this)       return this.$store.state.todos.list     }   },   methods: {     add (e) {        var value = this.todo && this.todo.trim()       if (value) {         this.$store.commit('todos/add', value)         this.todo = ''       }      },     toggle (todo) {       this.$store.commit('todos/toggle', todo)     },     remove (todo) {       this.$store.commit('todos/remove', todo)     },      doneEdit (todo) {       this.editedTodo = null       todo.text = todo.text.trim()       if (!todo.text) {         this.$store.commit('todos/remove', todo)       }     },     cancelEdit (todo) {       this.editedTodo = null       todo.text = this.beforeEditCache     },   },   directives: {     'todo-focus' (el, binding) {       if (binding.value) {         el.focus()       }     }   }, } </script>  <style> .done {   text-decoration: line-through; } </style> 

stores/todos.js

export const state = () => ({   list: [] })  export const mutations = {   add (state, text) {     state.list.push({       text: text,       done: false     })   },   remove (state, todo) {     state.list.splice(state.list.indexOf(todo), 1)   },   toggle (state, todo) {     todo.done = !todo.done   } } 

Any ideas how I can fix this?

like image 472
Run Avatar asked Sep 04 '17 21:09

Run


People also ask

Do not mutate Vuex store state outside mutation handlers object?

Error: [vuex] do not mutate vuex store state outside mutation handlers. The error means what it says. The solution is to mutate the store only with actions/mutations. You shallowly copy the array so it becomes a part of the store, then you continue to mutate it.

What is strict mode in Vuex?

In strict mode, whenever Vuex state is mutated outside of mutation handlers, an error will be thrown. This ensures that all state mutations can be explicitly tracked by debugging tools.

Are Vuex mutation async?

In Vuex, mutations are synchronous transactions: store.

What is the difference between Vuex mutations and actions?

Mutations are intended to receive input only via their payload and to not produce side effects elsewhere. While actions get a full context to work with, mutations only have the state and the payload .


2 Answers

It could be a bit tricky to use v-model on a piece of state that belongs to Vuex.

and you have used v-model on todo.text here:

<input class="edit" type="text" v-model="todo.text" v-todo-focus="todo == editedTodo" @blur="doneEdit(todo)" @keyup.enter="doneEdit(todo)" @keyup.esc="cancelEdit(todo)"> 

use :value to read value and v-on:input or v-on:change to execute a method that perform the mutation inside an explicit Vuex mutation handler

This issue is handled here: https://vuex.vuejs.org/en/forms.html

like image 155
Badis Merabet Avatar answered Sep 26 '22 10:09

Badis Merabet


Hello I have get the same problem and solve it with clone my object using one of the following:

{ ...obj} //spread syntax  Object.assign({}, obj) JSON.parse(JSON.stringify(obj)) 

For your code I think you need to replace this part

computed: {   todos () {     // console.log(this)     return this.$store.state.todos.list   } } 

With this

computed: {   todos () {     // console.log(this)     return {...this.$store.state.todos.list}   } } 

I don't make sure if this is the best way but hope this helpful for other people that have the same issue.

like image 41
user3772028 Avatar answered Sep 23 '22 10:09

user3772028