Computed property not updating from Vuex store object
Asked Answered
A

2

6

I have a bunch of class binding statements:

:class="{active: isActive('status', status.id)}"

Here's the method referred to above:

isActive: function (param, value) {
    if (!this.activeFilters.hasOwnProperty(param) && value === 'all' && param !== 'type') {
        return true;
    }
...etc
}

...and the computed property the method is looking at:

activeFilters() {
    return this.$store.state.activeFilters;
},

Which is in the Vuex state.

The problem is, these properties aren't updating when one of the dropdowns with the above class binding is clicked on. If I navigate to another route and then back, the active class has been applied just fine. Can I force the computed property to recompute so the class is applied immediately?

I understand that adding properties won't trigger reactivity, but according to this, if I replace the object with a fresh one, reactivity should be maintained. Well here's what I'm doing:

state.activeFilters = query;

...replacing the object. I am stumped.

Amboise answered 9/11, 2016 at 18:10 Comment(5)
this.$forceUpdate(); Is a bad practice. It's not even documented. I think you are doing something wrong. It's not angular. You should avoid this. Can you provide full example on jsfidde/jsbin/codepen?Sheppard
I mean basically all the relevant stuff is above - I'm deriving computed properties from a local object that is copied from the state. When the state changes, the computed properties don't update until I re-render - either by my newly discovered (and as you say undocumented) method, or by routing away and then back.Amboise
@Amboise I think if possible you should find a way to use computed properties for as much as possible, instead of method calls. Method calls, AFAIK, don't re-run when their dependent data changes like computed props do. For example, in this case, isActiveStatus could be a dictionary containing {key: true} for each key that is active. You could then use :style="{active: isActiveStatus[status.id]}".Marduk
To clarify, I think reactivity is not being triggered because isActive is a method. Your careful treatmenrt of activeFilters can't get around that.Marduk
If you're using Vuex, why are you calling your state directly? You should be using a getter, or at the very least using the mapState to call your state. This whole thing seems a bad practice.Embroil
T
2

Due to limitations in JavaScript, there are types of changes that Vue cannot detect with arrays and objects. You can read more about it here: https://v2.vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats

One simple solution is creating a method out of your computed property:

Before:

<Grid v-for="i in items" :items="items" />

<script>
  export default Vue.extend({
    .
    .
    .
    computed: {
      items() {
        return this.storedItems
      },
    }
  }
</script>

After:

<Grid v-for="i in items" :items="items" />

<script>
  export default Vue.extend({
    .
    .
    .
    methods: {
      items() {
        return this.storedItems
      },
    }
  }
</script>
Tumefaction answered 12/11, 2020 at 15:52 Comment(0)
A
0

Figured it out. After my function I need this to force the component to re-render:

this.$forceUpdate();
Amboise answered 9/11, 2016 at 20:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.