Reputation: 757
I'd like my view, using an id passed as a prop, to lookup an object's property in the store. The object in the store appears asynchronously, so the object might not be present right away. I'd like the view to react to the object's eventual appearance.
<template>
<div>
<h1>{{ title }}</h1>
</div>
</template>
<script>
export default {
props: ['id'],
computed: {
widget () {
let path = `widget/${this.id}`
return this.$store.state.widgets[path]
},
title () {
let widget = this.widget
return (widget) ? widget.data().fullName : 'nothing to see here'
}
}
}
</script>
Using vuex debug tools, I can watch the store widgets object start out empty and then get set with widgets: { 'widgets/someId': { ... } }
, but my vue doesn't seem to pick up the change. The title remains == 'nothing...'.
I tried making these methods, but I get the same behavior. I also tried replacing the whole widgets
object on the store, instead of one prop at a time (I think that's a requirement), but still no luck.
I think my question is very similar to this one, but the answer there is too terse. It just says "use a data item", but I don't really know what that is or how to use it (or why that will make the vue reactive).
Upvotes: 3
Views: 16285
Reputation: 43881
Mutations Follow Vue's Reactivity Rules
Since you're watching it go from empty to having some members, you are falling afoul of Vue's change detection caveats.
Vue cannot detect property addition or deletion.
You need to use Vue.set
when adding or deleting members, even in Vuex.
Upvotes: 6
Reputation: 20737
Your widget is most likely not reactive, because widget
itself does not change, and neither does widget.data
because it is a function you define. Vue does not "see" the changes in data when data
is called, because it is a function.
You have several ways of making your widget reactive. One is by precomputing your data and returning an object without functions. This could mean a performance drop when you have a lot of widgets, even though you do not need the data in most of them.
Another one is by potentially using the relatively new getter function/method. You would get your data with widget.data
and have a widget like
{
id: 1,
get data() {
// Whatever was in your function before
}
}
Remember that this is (I believe) an Ecmascript 6 feature, so you will likely need to run this through babel to be compatible with all relevant browsers.
Upvotes: 0