Within my Vuex store, I retrieve an array of rooms from a Firebase/Firestore API call. This array structure is as follows:
[{label:'Kitchen', description:'...'}, ...]
. To make this array accessible to my application, I utilize a Vuex getter function. Subsequently, in my components, I receive this array as a computed property. However, in my CRUD component, I route this "original" array through another computed property to attach various temporary properties to each object in the array - workable: () => this.rooms.map(val => { return ...val, editing: false, loading:false, ... })
. It's important to note that these additional properties are specific to the CRUD component and are not intended to be kept on the original array, the data source, or anywhere else within the app.
The current issue I am facing is related to updating these temporary properties in the CRUD array. Due to my understanding (or lack thereof), it seems that my computed properties would require setters to update the original array in the Vuex store. Consequently, this would prompt updates to propagate all the way back to the data source, completing a loop. (Please correct any misconceptions or inaccuracies in this explanation.)
Therefore, my question revolves around how I can update the temporary properties within the objects in my array without causing these changes (and properties) to cascade back to the data source?
I've provided a simplified version of my code below for better visualization:
// store.js (Vuex)
const actions = {
load: ({ commit, getters }) => {
const query = firebase.roomCollection.where('user', '==', getters.user.id);
const unsub = query.onSnapshot(snap => {
const rooms = snap.docs.map(val => {
return {
id: val.id,
...val.data(),
timestamp: val.data().timestamp.toDate(),
};
});
commit('setRooms', rooms);
});
},
};
const mutations = {
setRooms: (state, payload) => state.rooms = payload,
};
const state = {
rooms: [],
};
const getters = {
rooms: state => state.rooms,
};
// RoomCrud.vue
<template>
<ul>
<li v-for="room in workable" :key="`room-${i}`">
{{ room.label }}
<button @click="room.editing = !room.editing">Edit</button>
<br />
room: {{ room }} <!-- room.editing doesn't change when the Edit button gets clicked -->
</li>
</ul>
</template>
<script>
import { mapGetters } from 'vuex';
export default {
computed: {
...mapGetters(['rooms']),
workable() {
return this.rooms.map(val => {
return {
...val,
editing: false,
loading: false
};
});
}
}
}
</script>
I attempted to define workable
as an initially null data property and employ a method (setWorkable()
) to add the extra properties to each item in the array. On mounted()
, I called setWorkable()
, effectively separating workable
from
rooms</code. However, the drawback of this approach is the necessity to repeatedly call <code>setWorkable()
whenever a modification is made to one of the objects in the array that should ultimately reflect back to the source data.
While I understand this may be the only viable solution, I am hopeful there might exist a more efficient method using solely computed properties, thereby eliminating the need for manual re-rendering whenever a change occurs.
Feel free to request any additional details if necessary.