2
votes

I take data through the store using Vuex and API. I'm a beginner using Vuex. Is it because the data displayed previously has not been loaded? If it's true how to avoid this error.

NOTE : I retrieve data from a different server. I intend to make 1 sub domain for admin in this sub domain section I make the API data. in this case I retrieve data on localhost: 300 / (sub domain). and in the user section takes API data from this sub domain that is on localhost: 500

The data has been successful loaded but I got this 2 errors:

1. Error

[Vue warn]: Error in render: "TypeError: Cannot read property 'data' of undefined"

found in

---> at resources/js/components/Shop.vue

2. Error

TypeError: Cannot read property 'data' of undefined at Proxy.render (app.js:50035) at VueComponent.Vue._render (app.js:18850) at VueComponent.updateComponent (app.js:17094) at Watcher.get (app.js:17448) at new Watcher (app.js:17437) at mountComponent (app.js:17101) at VueComponent.Vue.$mount (app.js:22846) at VueComponent.Vue.$mount (app.js:25245) at init (app.js:18443) at createComponent (app.js:19914)

Data : IMG RESULT

If I delete this code, the errors are gone:

  <div class="col-sm-6 col-md-4 col-lg-3 p-b-35 " v-for="(product,index) in productlist.products.data"  :class="product.category_slug">

Shop.vue

export default {
  components:{
      'pagination':Pagination,
  },
  data(){
    return{
      selected: "Choose Province",
     inputSearch:'',
     filterForm:{
       color:[],
       sortBy:'',
       productType:[],
       size:[],
       },
       product_color_id:0,
       quickview:null,
       showQuickview:false,

    }
  },
  computed: {
      productlist(){
        return this.$store.getters.productlist;
      }

  },
  created(){
    if (this.productlist.length ) {
       return;
    }
    this.$store.dispatch('GetProductList');
  },

Action.js

export default{
  GetProductList(context){
     let url ='http://localhost:300/api/v1/product';
  axios.get(url)
      .then(response => {
        context.commit('dataProduct',response.data);
        window.scrollTo(0, 0);
        if($('.js-show-filter').hasClass('show-filter')) {
            $('.js-show-filter').removeClass('show-filter');
            $('.panel-filter').slideUp(400);
        }
        if($('.js-show-search').hasClass('show-search')) {
            $('.js-show-search').removeClass('show-search');
            $('.panel-search').slideUp(400);
        }
      })
      .catch(error => {
          console.log(error);
      });
  }
}

Getters.js

export default{
  productlist(state){
  return  state.productlist;
},

}

Mutations.js

export default{
  dataProduct(state,payload){
    state.productlist = payload;
  }
}

Store.js

import actions from './actions';
import mutations from './mutations';
import getters from './getters';
export default{
  state:{
    productlist:[],
  },
  getters,
  mutations,
  actions
}
2
please note that in Action.js, the port used to communicate with localhost is 300 instead of the default 3000.P3trur0
I retrieve data from a different server. I intend to make 1 sub domain for admin in this sub domain section I make the API data. in this case I retrieve data on localhost: 300 / (sub domain). and in the user section takes API data from this sub domain that is on localhost: 500. @P3trur0Faris Dewantoro
Did you tried to initialize productlist in the store? productlist: { products: {}}?Zysce
do I have to initialize all the data? because if only in the product section I get another error @ZysceFaris Dewantoro

2 Answers

1
votes

You must initialize all available data to avoid this error. because when the page is opened. data is not directly received, therefore you get this error and the data is still obtained. add this code to the store section:

import actions from './actions';
import mutations from './mutations';
import getters from './getters';
export default{
  state:{
    productlist:{
      products:{},
      categories:[],
      pagination:{},
      productcolors:[],
      productsizes:[]

    },
  },
  getters,
  mutations,
  actions
}

and don't forget to initialize according to the data type

3
votes

When your app is first loaded your productList is not yet initialized, so it's objects' properties aren't accessible. What you need to do is wrap your v-for element with another element with v-if directive like so:

<template v-if="productList.products.data">
    <div class="col-sm-6 col-md-4 col-lg-3 p-b-35 " v-for="(product,index) in productlist.products.data" :class="product.category_slug">
</template>

On a side note - a good practice is to use :key together with v-for. Key should be a unique value, for example object's id. If you don't do that, you may later encounter problems with i.e. removing your array's elements (objects' properties might get messed up).

Also, notice that I wrapped your v-for with another div instead of placing v-if inside of v-for div. It's because if you use v-if in the same element as your v-for the condition will be checked with every loop which in this case isn't necessary.