简体   繁体   中英

Vue.js (vuex). Computed property returns undefined when reloading the page. (Hard coded array of objects data in vuex)

I am building a shoe shop with Vue and the problem is that I am getting undefined when reloading the page when I am trying to access a getter through computed property on the ShoeDetail component.I am storing some hard coded array of objects data in the vuex state. In the Shoe component I am looping through the data with v-for and outputting in the Men view, that is working for me, all avaliable shoes are displayed. When a user clicks on the shoe image a new route is loaded for each shoe with further details for that shoe which got clicked. I am using the id for dynamic routing. Now i have a getter in vuex

getProductById: (state) => (id) => {
      return state.sneakers.find((sneaker) => sneaker.productId === id);
    },

then I access it through a computed property:

   product() {
      return this.$store.getters.getProductById(this.$route.params.id);
    },

that works fine and I can output the data stored in vuex state by interpolitaion like:

{{product.brand}}

When I reload the page I get this error:

**[Vue warn]: Error in render: "TypeError: Cannot read property 'brand' of undefined"
found in
---> <Detail> at src/components/ShoeDetail.vue
       <App> at src/App.vue
         <Root>**

I have tried to use v-if="product" but since im not making an API call this shouldn't be relevant. I have also installed the createPersistedState but it still doesn't work. I am really stuck here and a hint on why im getting undefined on page reload would be appreciated

My vuex:


  
  
  
    import Vue from 'vue';
    import Vuex from 'vuex';
    import createPersistedState from 'vuex-persistedstate';

    Vue.use(Vuex);

    export default new Vuex.Store({
      plugins: [
        createPersistedState({
          key: 'keyname',
          storage: window.localStorage,
        }),
      ],
      state: {
        sneakers: [
          {
            productId: 1,
            productno: 1234,
            brand: 'nike',
            gender: 'men',
            size: 5,
            price: 150,
            image: require('@/assets/images/nike-air-zoom.jpg'),
          },
          {
            productId: 2,
            productno: 1235,
            brand: 'adidas',
            gender: 'men',
            size: 10,
            price: 140,
            image: require('@/assets/images/sneakers.jpg'),
          },

          {
            productId: 3,
            productno: 1236,
            brand: 'adidas',
            gender: 'men',
            size: 10,
            price: 130,
            image: require('@/assets/images/man-holding-nikes.jpg'),
          },
          {
            productId: 4,
            productno: 1237,
            brand: 'nike',
            gender: 'men',
            size: 5,
            price: 120,
            image: require('@/assets/images/nike-air-zoom.jpg'),
          },
          {
            productId: 5,
            productno: 1238,
            brand: 'adidas',
            gender: 'men',
            size: 10,
            price: 110,
            image: require('@/assets/images/sneakers.jpg'),
          },

          {
            productId: 6,
            productno: 1239,
            brand: 'adidas',
            size: 10,
            price: 100,
            image: require('@/assets/images/man-holding-nikes.jpg'),
          },
        ],
      },
      getters: {
        getProducts: (state) => {
          return state.sneakers;
        },
        getProductById: (state) => (id) => {
          return state.sneakers.find((sneaker) => sneaker.productId === id);
        },
      },
    });

The Shoe component:


  
  
  
    <template>
      <div class="shoe-container">
        <div class="shoe-card" v-for="element in products" :key="element.id">
          <router-link
            :to="{ name: 'ShoeDetail', params: { id: element.productId } }"
            ><img :src="element.image" tag="img" alt="" class="shoe-card__image"
          /></router-link>
          <p class="shoe-card__model">{{ element.brand }}</p>
          <p class="shoe-card__price">{{ element.price }} $</p>
        </div>
      </div>
    </template>

    <script>
    export default {
      computed: {
        products() {
          return this.$store.getters.getProducts;
        },
        product() {
          return this.$store.getters.getProductById(this.$route.params.id);
        },
      },
    };
    </script>

    <style lang="scss" scoped>
    @import '../sass/components/shoe';
    </style>

The men view:


  
  
  
    <template>
      <div>
        <navbar></navbar>
        <sub-nav></sub-nav>
        <filter-section></filter-section>
        <section class="shoes">
          <shoe></shoe>
        </section>
      </div>
    </template>

    <script>
    import Navbar from "../components/Navbar.vue";
    import SubNav from "../components/SubNav.vue";
    import FilterSection from "../components/FilterSection.vue";
    import Shoe from "../components/Shoe.vue";

    export default {
      components: {
        Navbar,
        SubNav,
        FilterSection,
        Shoe
      }
    };
    </script>

    <style lang="scss" scoped>
    @import "../sass/views/men";
    </style>

The ShoeDetail component:


  
  
  
    <template>
      <div class="details">
       
        <h1>This is details</h1>
        <h2>{{ product.brand }}</h2>

      </div>
    </template>
    <script>
    export default {
      name: 'detail',

      computed: {
        product() {
          return this.$store.getters.getProductById(this.$route.params.id);
        },
      },
    };
    </script>

    <style lang="scss" scoped>
    @import '../sass/components/shoeDetail';
    </style>

Thanks for the answer I was able to fix it by adding parseInt in the computed property of ShoeDetail.

 computed: { product() { return this.$store.getters.getProductById( parseInt(this.$route.params.id) ); }, }

Do this in the ShoeDetail component:

data: () => {
    data: '',
},
methods: {
    getProduct () {
    this.product = this.$store.getters.getProductById(this.$route.params.id);
    },
},
mounted () {
    this.getProduct();
}

and it should work:)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM