Reputation: 147
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>
Upvotes: 0
Views: 1031
Reputation: 147
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)
);
},
}
Upvotes: 1
Reputation: 31
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 :)
Upvotes: 0