I use Vue with Vuex. In one case I use Ajax to get a presentation value. Somewhere on the way, probably in computed
it's no longer reactive.
In my component:
props: [ 'x', 'y' ],
template: `
<div class="presentation">
{{ presentation }}
</div>
`,
computed: {
presentation() {
return this.$store.getters.presentation({ x: this.x, y: this.y });
}
}
Vuex store:
const store = new Vuex.Store({
state: {
table: {
data: []
}
},
...
Vuex actions:
I call an url with ajax and return a promise. I also commit a mutation.
actions: {
save: (context) => {
let uri = 'some/uri';
let params = {};
let value = 'A value';
return axios
.post(uri, params)
.then((response) => {
context.commit('setPresentation', value);
})
.catch((error) => {
console.log('error');
})
.finally(() => {});
},
},
Vuex mutations:
mutations: {
setPresentation: (state, value) => {
let pos = state.table.pos;
state.table.data[pos.y][pos.x].presentation = value;
},
}
Vuex getters:
getters: {
presentation: (state) => (pos) => {
return state.table.data[pos.y][pos.x].presentation;
}
},
I've already make sure of the following:
table.data
state to a default value to make it reactiveNotes:
presentation
from more than one component.Question(s)
You need to use Vue.set
instead of state.table.data[pos.y][pos.x].presentation = value;
See https://v2.vuejs.org/v2/guide/list.html#Caveats for details
Try to update your mutation with the following code:
if (!state.table.data[pos.y]) {
Vue.set(state.table.data, pos.y, [])
}
Vue.set(state.table.data[pos.y], pos.x, { presentation: value })
A word from me, the OP (Original poster):
Why it failed the first times was that I only set the last part { presentation: value }
with Vue.set
as I already has pos.y
and pos.x
set in another ajax call.
For Vue to be fully aware if the change I needed to set everything that has not already been set in state, with Vue.set
. So I needed use Vue.set
to set pos.y
and pos.x
as well.
Also see another excellent answer below.
Vue cannot detect changes to an array when you directly set an item with the index