Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reactive getter in vuex?

Tags:

vue.js

vuex

I have getter in vuex which returns item from list

const store = new Vuex.Store({
    state: { arr: {
        1: {name: 'one', attr: true},
        2: {name: 'two', attr: false} 
    },
    mutations: {
        setArrItemName(state, id, name) {
            Vue.set(state.arr, id, name);
        }
    },
    getters: {
        arrItemById(state, getters) => (id) => {
            const item = state.arr[id];
            if(item) return item;
            return {
                 name: 'default', attr: true
            };
        }
    }
})

If I output it in template

{{ $store.state.arr[1]['name'] }}

it updates fine when another part calls

this.$store.commit('setArrItemName', 1, 'new name');

But if template contains

{{ $store.getters.arrItemById(1).name }}

Then it's not updated

Problem: this getter is used in different places and I do not want to duplicate this code

<template v-if='$store.state.arr[id]'>
    {{ $store.state.arr[id].name }}
</template>
    Default
<template v-else>
</template>

If 'default' some day changes, or any other attribute of default object then it should be updated in different places.

like image 572
Jackson J Avatar asked May 12 '17 13:05

Jackson J


2 Answers

Try using computed properties for accessing your getters. First, import the mapGetters function from Vuex:

import {mapGetters} from 'vuex';

Then, add computed properties for the getters you want as follows:

computed: {
    ...mapGetters({
        getterName: 'your-getter-name-in-store'
    })
} 

We use a spread operater ( ... ) while using the mapGetters helper; you can read more about why here.

Then, in your template, use {{ getterName }}.

This also overcomes your problem of code duplication, as you won't need to use this.$store.getters everywhere.

like image 108
Vamsi Krishna Avatar answered Oct 26 '22 08:10

Vamsi Krishna


You can't get reactive on getter which is not pure. You can create a computed property on local.

Sources : https://github.com/vuejs/vuex/issues/145#issuecomment-230488443

I made some research, and you can use computed function with a getter inside :

  computed: {
    arr() {
            return this.$store.getters.arrItemById(this.id);
      }
  },

Here is a jsfiddle example.

like image 20
Tobino Avatar answered Oct 26 '22 09:10

Tobino