1
votes

The Vuex storage has a getter which returns object by id. But I can't use the data from the getter.

When i use computed: data come from getter after the component was rendered, and DOM still empty (until I'm not clicking on component in vue devtools. If i click, computed run again, and element are redrawn and filled with the data from data())

if I call the getter directly during the definition of data() objects, {{ cardData.content }} in DOM can be seen immediately, but this.cardData.title returns an error Cannot read property 'title' of undefined. Why?

Vuex storage

export const store = new Vuex.Store({
    state: {
        "cards": [
            {
                "position": null,
                "title": "Head Text",
                "id": 132,
                "content": "LoremIpsum",
                "type": "text",
            },
            {
                "position": null,
                "title": "Head Text 2",
                "id": 138,
                "content": "LoremIpsumLoremIpsum",
                "type": "text",
            }
        ]
    },

    getters: {
        cards: (state) => state.cards
    }
});

vue component,

<template>
<div>
  <h1>{{ cardTitle }}{{ cardTitle2 }}</h1>
  <div>{{ cardData.content }}</div>
</div>
</template>


<script>
  export default {
    props: ['id'],
    data() {
      return {
        cardData: this.$store.getters.cards.find((card) => card.id == this.id),
        cardTitle: this.cardData.title,
        cardData2: null,
        cardTitle2: null
      }
    },
    computed: {
      GetData: function() {
        this.cardData2 = this.$store.getters.cards.find((card) => card.id == this.current);
        this.cardTitle2 = this.cardData2.title;
      },
    } 
  }

</script>
3

3 Answers

3
votes

Why not just have a computed property which returns desired title, it can be just following as documented here:

computed: {
  cardTitle: function() {
   var card = this.$store.getters.cards.find((card) => card.id == this.current)
   return card.title
  },
} 

Now you can use {{this.cardTitle}} in the DOM.

1
votes

Getting Vuex State into Vue Components

So how do we display state inside the store in our Vue components? Since Vuex stores are reactive, the simplest way to "retrieve" state from it is simply returning some store state from within a computed property

In your case you have card array in vuex state, and you use data method to return array. That is not proper way to handle this case. You need to use computed method as a getter. Whenever this.$store.state.card changes, it will cause the computed property to re-evaluate, and trigger associated DOM updates:

 computed: {
    cardData() {
      return this.$store.getters.cards
    }
  }

And in your component template you can display properties from cardData array, whether it needs to be title, content, type, id...etc. You don't need to create cardTitle, cardId, cardType variables for every property in array, just add property after cardData:

<template>
  <div class="card">
  <h1>{{ cardData.title }}</h1>
  <p>{{ cardData.content }}</p>
  </div>
</template>

Here is jsFiddle example for your case, filtered cardData array by id.

0
votes

It is more efficient if you loop through the array using v-for as indicated in the vue.js documentation homepage.

computed: {
     cards () {
          return this.$store.getters.cardData
     }
}

this.$store.getters.cardData in computed being what you have initialised in getters: i.e

getters: {
    cardData: (state) => state.cards
}

and state like so:

state: {
    cards: []
}

then in your template tag, you can loop through the dataset array like so:

<template id="insert id here">
    <ul v-for"card in cards" :key="card.id">
       <li> {{ card.title }}</li>
       <li> {{ card.content }}</li>
    </ul>
</template>