Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating state of vuex array when one item has some changes

Tags:

I have an array called cases in my vuex store.

I want to update the array with the new content when I update a few fields within an existing item in the array.

I thought I could do something like this in my mutation but doesn't work and get the error typeError: undefined is not an object (evaluating 'state.objects.find')

EDIT_CASE (state, payload) {     const item = state.objects.find(item => item.id === payload.recordId); Object.assign(item, payload.case_status); 

my array is as follows:

[     {         "case_name": "Laptop not working",         "case_status": "live",         "case_summary": "This is some summary content",         "createdBy": "zippy",         "createdDate": "2018-06-21T15:20:22.932Z",         "id": "-LFXvk9yY5c-O8yIdf8k"     },     {         "case_name": "Something else",         "case_status": "live",         "case_summary": "This is some summary content",         "createdBy": "zippy",         "createdDate": "2018-06-21T15:20:22.932Z",         "id": "-STVvk9yY5c-O3yiTy8k"     } ] 

I also think from what I have read Vue does not observe changes within arrays so it may be I'm going completely the wrong way with this, and need to remove and then re-add the array item?

Basically I have a list, I make a change to my backend, now I want that list to reflect the changes I have made through updating the cases state, can anyone help?

like image 805
Paul Avatar asked Jul 03 '18 08:07

Paul


People also ask

How do I update my Vuex state?

Vuex stores are reactive. When Vue components retrieve state from it, they will reactively and efficiently update if the store's state changes. You cannot directly mutate the store's state. The only way to change a store's state is by explicitly committing mutations.

Does Vuex keep state on refresh?

However, when the page is refreshed, the data in vuex will be reinitialized, resulting in data loss. Because the data in vuex is saved in the running memory, when the page is refreshed, the page will reload the vue instance, and the data in vuex will be re assigned.

What is the difference between mutations and actions in Vuex?

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 .

Is Vuex state mutable?

Vuex state is mutable, hence we can directly create state variables and assign values to them. Redux uses Reducers, which are pure functions that take the previous state and action, and return the next state.


2 Answers

There is no array issue with your example because you try to change an object property - not array element reference. The problem is in Object.assign(item, payload.case_status); - you should provide an object not just a field. (Also you said that array called cases but example has objects, maybe this is problem too);

So this should work:

EDIT_CASE (state, payload) {     const item = state.objects.find(item => item.id === payload.recordId);     Object.assign(item, payload); } 

The error:

undefined is not an object

I think, it is related to Object.assign because you pass field to it which is undefined probably.

P.S. There is small example to help you understand when array issue appears and when everything works fine. See code comments :)

new Vue({    el: "#app",    data: {      todos: [        { text: "Learn JavaScript" },        { text: "Learn Vue" },        { text: "Play around in JSFiddle" },        { text: "Build something awesome" }      ]    },    methods: {      // work because object property is reactive    	changeItemProperty() {      	this.todos[3].text = "changedItemProperty";      },      // same reason, properties are reactive      changeItemWithAssign() {      	Object.assign(this.todos[3], { text: "changedItemWithAssign" });      },      // does not work, can not track changes in array      // also this will break all attempts to change TEXT property in UI      // because property becomes not reactive after this due to new object      // try to changeItemProperty or  changeItemWithAssign - does not work!      // changeItem2 will fix it :)      changeItem() {      	this.todos[3] = { text: "changedItem" }      },      // works      changeItem2() {      	Vue.set(this.todos, 3, { text: "changedItem2" });      }	    }  })
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>  <div id="app">    <div v-for="todo in todos" :key="todo.text">       {{todo.text}}    </div>    <button @click="changeItemProperty">changeItemProperty(works)</button>    <button @click="changeItemWithAssign">changeItemWithAssign(works)</button>    <button @click="changeItem">changeItem(does not work!)</button>    <button @click="changeItem2">changeItem2(works)</button>  </div>
like image 187
Max Sinev Avatar answered Oct 06 '22 09:10

Max Sinev


JavaScript (not specific to Vue) can not detect setting the value of an Array item directly by index arr[3] = 'stop'; It also can not detect adding a new key or deleting an existing key from an Object. You must be defining the initial state of the store, e.g.

const store = new Vuex.Store({   state: {     objects: []   },   mutations: {     EDIT_CASE (state, payload) {       const index = state.objects.findIndex(item => item.id === payload.id);       if (index !== -1) state.objects.splice(index, 1, payload);     }   } }) 
like image 26
IVO GELOV Avatar answered Oct 06 '22 09:10

IVO GELOV