简体   繁体   中英

VueJS with Vuex - Replace item (object) in array stored in Vuex with splice doesn't re-render list of items

I have an array of records. Each record is an object with _id (mongo id) , title, and value (value is an object with amount and currency).

I'm showing the list of records with v-for when ':key' of the list is the id of the record.

It works when I add a record, (using records.push() in the store), and delete a record (using records.splice(idx, 1) ), But when I'm trying to edit a record and change the title or value.amount the list does not re-render and show the list without the change (using records.splice(idx, 1, updatedRecord))

Here My Code: Record List

 <template> <ion-list> <ion-item> <ion-label>Date</ion-label> <ion-label>Title</ion-label> <ion-label>Value</ion-label> <ion-label /> </ion-item> <RecordPreview v-for="record in records":key="record._id":record="record" @onEditRecord="onEditRecord" @onDeleteRecord="onDeleteRecord" /> </ion-list> </template> <script> import { IonList, IonItem, IonLabel } from '@ionic/vue'; import RecordPreview from './RecordPreview.vue'; export default { name: 'RecordList', components: { RecordPreview, IonList, IonItem, IonLabel, }, props: { records: { type: Array, default: () => [], }, }, emits: ['onEditRecord', 'onDeleteRecord'], setup(_, { emit }) { function onEditRecord(record) { emit('onEditRecord', record); } function onDeleteRecord(record) { emit('onDeleteRecord', record); } return { onEditRecord, onDeleteRecord, }; }, }; </script>

Vuex record module

 import recordService from '../../services/record.service'; export const recordModule = { state: () => ({ records: [], }), actions: { async getRecords({ commit }) { const records = await recordService.getRecords(); commit('setRecords', records); }, async addRecord({ commit }, record) { const newRecord = await recordService.addRecord(record); commit('addRecord', newRecord); }, async updateRecord({ commit }, record) { const res = await recordService.updateRecord(record); if (res.modifiedCount > 0) { commit('updateRecord', record); } }, async removeRecord({ commit }, recordId) { const res = await recordService.removeRecord(recordId); if (res.deletedCount > 0) { commit('removeRecord', recordId); return true; } return false; }, }, mutations: { setRecords(state, records) { state.records = records; }, addRecord(state, record) { state.records.push(record); }, updateRecord(state, updatedRecord) { const recordIdx = state.records.findIndex((rec) => rec._id === updatedRecord._id); state.records.splice(recordIdx, 1, updatedRecord); }, removeRecord(state, recordId) { const recordIdx = state.records.findIndex((rec) => rec._id === recordId); state.records.splice(recordIdx, 1); }, }, getters: { records(state) { return state.records; }, }, };

To get the records I'm using getter from the store placed on the parent component of RecordList like that:

 const records = computed(() => store.getters.records);


PS I tried to create a deep copy of the array and replace all the array. I also tried to create a deep copy of the record, then change and replace it. And I think the problem is with the key, coz when I tried to change the:key from 'record._id' to 'record 'it re-render the list when I replaced the item (I guess it work because the pointer of the object was changed)

If you are fetching records from an API I recommend that you update by fetching from the API, and if you want to update the item within your state, try this:

updateRecord(state, updatedRecord) {
  const { title, value } = updatedRecord;
  const recordIdx = state.records.findIndex((rec) => rec._id === updatedRecord._id);

  recordIdx.title = title
  recordIdx.value = value 
  ...
},

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM