0
votes

I ran into a problem earlier where mapState() does not create (simple value retrieving) getters automatically for store modules. Or maybe it was a timing issue. The docs say this:

"When a component needs to make use of multiple store state properties or getters, declaring all these computed properties can get repetitive and verbose. To deal with this we can make use of the mapState helper which generates computed getter functions for us, saving us some keystrokes:"

https://vuex.vuejs.org/guide/state.html

Using mapState() in a component computed property worked great - until I moved some of that state into a module, at which point it quit working. Adding a getter to pull the state property did work but I dislike the code duplication when retrieving simple, not computed, values. If it was due to timing, is there a store.ready(app.use(store)) function somewhere?

// store.js
import { createStore } from 'vuex';
import products from './products.js'
import cart from './cart.js'

const store = createStore({
   modules:{
      products,
      cart
   },
   state() {
      return {
         isLoggedIn: false,
      }
   },
   mutations: {
      login(state) {
         state.isLoggedIn = true;
      },
      logout(state) {
         state.isLoggedIn = false;
      },
   },
})

export default store;
// products.js

export default {
   state() {
      return {
         products: [
            {
               id: 'p1',
               image:
                  'https://upload.wikimedia.org/wikipedia/commons/thumb/5/5a/Books_HD_%288314929977%29.jpg/640px-Books_HD_%288314929977%29.jpg',
               title: 'Book Collection',
               description:
                  'A collection of must-read books. All-time classics included!',
               price: 99.99,
            },
         ],
      }
   },
   getters:{
      products(state){
         return state.products;
      }
   }
}
<!-- productList.vue -->

<template>
  <section>
    <ul>
      <product-item
        v-for="prod in products"
        :key="prod.id"
        :id="prod.id"
        :title="prod.title"
        :image="prod.image"
        :description="prod.description"
        :price="prod.price"
      ></product-item>
    </ul>
  </section>
</template>

<script>
import ProductItem from '../components/products/ProductItem.vue';
import { mapState } from 'vuex'
//import { mapGetters } from 'vuex'

export default {
  components: {
    ProductItem,
  },
  computed: {
    ...mapState([       //This does not work
      'products'
    ])
    // ...mapGetters([    This does
    //   'products'
    // ])
  },
  mounted(){
    console.log(this.products)
  }
};
</script>

<style scoped>
  ul {
    list-style: none;
    margin: 2rem auto;
    padding: 0;
    max-width: 40rem;
  }
</style>
1
You can use mapState with modules. Please update the question to show the code that uses it with modules.tony19
I added some code. I should mention that I see this.products in the console, so it's there somehow. But v-for doesn't pick it up when I use mapState. It does pick it up when I switch to mapGetters. And it was working before I switched to modules.Daemach
Are your modules namespaced? They aren't in your question but that's not very typicalPhil

1 Answers

0
votes

Module state is always namespaced. For example, your products state in the products module is only available under

//         👇 module 👇 state
store.state.products.products

To use mapState with a module, you can use either of these options

computed: {
  ...mapState({
    products: state => state.products.products
  }),
  ...mapState("products", {
    products: state.products
  })
  ...mapState("products", [
    "products"
  ])
}

Each of these will map the products state from the products module to this.products in your component.


Your getters work because your modules are not namespaced and therefore...

By default, actions, mutations and getters inside modules are still registered under the global namespace

See https://vuex.vuejs.org/guide/modules.html#namespacing