I have a component that receives an array of Villager
into it's prop
from a parent component. The parent component pulls that array from this.$store.state
.
return this.$store.state.villages.find(value => value.id === 0).villagers
I execute a this.$store.mutation
commit to alter the given array afterwards. The mutation does work as you can see in the screenshot further down. However the component I am in is not re-rendering and is still showing 3 instead of 2 items.
The reactive chain seems to be broken somewhere but I can not pinpoint the fiend. I thought the props
value is a reactive mechanism. As you can see in the screenshot it's value has changed but the DOM was not updated accordingly.
I tried to extract the relevant parts for the questions
store/index.ts
[...]
export default new Vuex.Store({
state: {
villages: [
{
id: 0,
name: 'Peniuli',
foundingDate: 20,
villagers: [
{
id: '33b07765-0ec6-4600-aeb1-43187c362c5a1',
name: 'Baltasar',
bloodline: 'Gent',
occupation: 'Farmer'
},
[...]
mutations: {
disbandVillager (state, payload) {
const villagerId = payload.id
const village = state.villages.find(value => value.id === 0)
console.debug('disbanding villager:', villagerId)
if (!_.isNil(village)) {
console.debug('bfore:', village.villagers)
_.remove(village.villagers, function (n) {
return n.id === villagerId
})
console.debug('after:', village.villagers)
}
}
},
[...]
Village.vue
<template>
<Villagers :villagers="playerVillage.villagers"></Villagers>
</template>
[...]
computed: {
playerVillage: function () {
return this.$store.state.villages.find(value => value.id === 0)
}
}
[...]
Villagers.vue
<template>
<v-container>
<v-card v-for="villager in villagers" :key="villager.id">
<v-row>
<v-col>
<v-card-title>Name: {{villager.name}}</v-card-title>
</v-col>
<v-col>
<v-card-title>Bloodline: {{villager.bloodline}}</v-card-title>
</v-col>
<v-col>
<v-card-title>Occupation: {{villager.occupation}}</v-card-title>
</v-col>
<v-col v-if="managable">
<DisbandButton :villager="villager"></DisbandButton>
</v-col>
</v-row>
</v-card>
</v-container>
</template>
<script>
import DisbandButton from '@/components/village/DisbandButton'
export default {
name: 'Villagers',
components: { DisbandButton },
props: [
'villagers',
'managable'
]
}
</script>
DisbandButton.vue
<template>
<v-btn @click="disbandVillager" color="red">Disband</v-btn>
</template>
<script>
export default {
name: 'DisbandButton',
props: ['villager'],
methods: {
disbandVillager: function () {
this.$store.commit('disbandVillager', { id: this.villager.id })
}
}
}
</script>
Assuming that's lodash then I believe the problem is that you're using _.remove
.
Internally _.remove
is implemented in such a way that it doesn't trigger Vue's reactivity system. Specifically here:
https://github.com/lodash/lodash/blob/ded9bc66583ed0b4e3b7dc906206d40757b4a90a/lodash.js#L3859
That's using the default Array splice
method, not the custom override provided by Vue.
Something like this should work:
village.villagers = village.villagers.filter(function (n) {
return n.id !== villagerId
})
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.