8
votes

I'm having trouble understanding how to interact with my local state from my vuex state. I have an array with multiple items inside of it that is stored in vuex state. I'm trying to get that data from my vuex state into my components local state. I have no problems fetching the data with a getter and computed property but I cannot get the same data from the computed property into local state to manipulate it. My end goal is to build pagination on this component.

I can get the data using a getters and computed properties. I feel like I should be using a lifecycle hook somewhere.

Retrieving Data

App.vue:

I'm attempting to pull the data before any components load. This seems to have no effect versus having a created lifecycle hook on the component itself.

export default {
  name: "App",
  components: {},
  data() {
    return {
      //
    };
  },
  mounted() {
    this.$store.dispatch("retrieveSnippets");
  }
};

State:

This is a module store/modules/snippets.js

const state = {
   snippets: []
}

const mutations = {
SET_SNIPPETS(state, payload) {
    state.snippets = payload;
  },
}

const actions = {
retrieveSnippets(context) {
    const userId = firebase.auth().currentUser.uid;
    db.collection("projects")
      .where("person", "==", userId)
      .orderBy("title", "desc")
      .onSnapshot(snap => {
        let tempSnippets = [];
        snap.forEach(doc => {
          tempSnippets.push({
            id: doc.id,
            title: doc.data().title,
            description: doc.data().description,
            code: doc.data().code,
            person: doc.data().person
          });
        });
        context.commit("SET_SNIPPETS", tempSnippets);
      });
  }
}

const getters = {
  getCurrentSnippet(state) {
    return state.snippet;
},

Inside Component

data() {
    return {
      visibleSnippets: [],
   }
}
computed: {
stateSnippets() {
      return this.$store.getters.allSnippets;
    }
}

HTML:

you can see that i'm looping through the array that is returned by stateSnippets in my html because the computed property is bound. If i remove this and try to loop through my local state, the computed property doesn't work anymore.

<v-flex xs4 md4 lg4>
  <v-card v-for="snippet in stateSnippets" :key="snippet.id">
    <v-card-title v-on:click="snippetDetail(snippet)">{{ snippet.title }}</v-card-title>
  </v-card>
</v-flex>

My goal would be to get the array that is returned from stateSnippets into the local data property of visibleSnippets. This would allow me to build pagination and manipulate this potentially very long array into something shorter.

2

2 Answers

10
votes

You can get the state into your template in many ways, and all will be reactive.

Directly In Template

<div>{{$store.state.myValue}}</div>
<div v-html='$store.state.myValue'></div>

Using computed

<div>{{myValue}}</div>
computed: {
  myValue() { return this.$store.state.myValue }
}

Using the Vuex mapState helper

<div>{{myValue}}</div>
computed: {
  ...mapState(['myValue'])
}

You can also use getters instead of accessing the state directly.

The de-facto approach is to use mapGetters and mapState, and then access the Vuex data using the local component.

3
votes

I guess you are getting how Flux/Vuex works completely wrong. Flux and its implementation in Vuex is one way flow. So your component gets data from store via mapState or mapGetters. This is one way so then you dispatch actions form within the component that in the end commit. Commits are the only way of modifying the store state. After store state has changed, your component will immediately react to its changes with latest data in the state.

Note: if you only want the first 5 elements you just need to slice the data from the store. You can do it in 2 different ways:

1 - Create a getter.

getters: {
    firstFiveSnipets: state => {
        return state.snipets.slice(0, 5);
    }
}

2 - Create a computed property from the mapState.

computed: {
    ...mapState(['allSnipets']),
    firstFiveSnipets() {
        return this.allSnipets.slice(0, 5);
    }
}