4

Newbie question here with Vuex. Probably doing something wrong. I have this simple store:

export default new Vuex.Store({
  strict: process.env.NODE_ENV !== 'production',
  state: {
    items: []
  },
  getters: Object.assign({}, itemGetters),
  mutations: Object.assign({}, itemMutations),
  actions: Object.assign({}, itemActions),
});

With the getters being like this:

export const itemGetters = {
  allItems: state => state.items,
  itemById: (state, getters) => id => getters.allItems.filter(s => s.id === id)[0],
};

Now, I have this view which has a nested view in it. Basically an information modal for each item.

If I click on the link, I expect to go and see the element modal with the item filled.

export default {
  name: 'Landing',
  computed: {
    items() {
      return this.$store.getters.allItems;
    }
  },
  created() {
    if (this.items.length === 0) {
      this.$store.dispatch('allItems');
    }
  }
};

Now, entering that view works as expected and if I click on the nested view, which is as follows:

<template>
  <div class="text">
    <h1 class="heading">{{ item.title }}</h1>
  </div>
</template>
<script>
export default {
  name: 'InfoModal',
  props: ['id'],
  computed: {
    item() {
      return this.$store.getters.itemById(this.id);
    }
  }
};
</script>

It does work too. However, it doesn't work when I just reload the page and errors due to item not being there yet.

Thing is I could do the same and add an action to fetch the item from the API if it's not there yet but I don't really see the point because I'll have all of them eventually.

What do I need to do here?

Antonio Laguna
  • 8,973
  • 7
  • 36
  • 72
  • Check if item is undefined and if so, show a loading screen until it is defined – Derek Pollard Apr 27 '18 at 14:56
  • vuex.state is cleared up when reload. check [Vuex state on page refresh](https://stackoverflow.com/questions/43027499/vuex-state-on-page-refresh); normally what I do is redirect to login/home view if the user reload. but if you don't, look into of the answer of above URL. – Sphinx Apr 27 '18 at 15:58

1 Answers1

6

The thing is the computed properties get evaluated first pretty early in the components lifecycle.

If you know that the item will eventually (and quickly) be there, simply return a default value in the computed when the item isn't there yet, so Vue has something to render (even if empty) in this first execution:

  computed: {
    item() {
      return this.$store.getters.itemById(this.id) || {}; // added {} as default.
    }
  }

The computed will be automatically re-evaluating (because the getter will) as soon as the item becomes available.

acdcjunior
  • 132,397
  • 37
  • 331
  • 304
  • So this removes the error, but it doesn't render on refresh – Antonio Laguna Apr 27 '18 at 16:43
  • Hm, I see. Vuex really is reset when page refreshes, so you do need to re-fetch the data (the change proposed in this answer will allow you to fetch it without error) OR you should use a persistent Vuex store, that saves the data in the browser local storage or cookie. – acdcjunior Apr 27 '18 at 17:00
  • Actually it was an odd issue. `this.id` was set to a string but to a number when normal flow happened. – Antonio Laguna Apr 27 '18 at 17:13