Search code examples
vue.jsvuejs2nuxt.jsvuetify.jsvuex

Vuejs Error: Property or method "cart" is not defined on the instance but referenced during render. Property"cartItems" is not defined


I have an error trying to get data from my vuex store.

Property or method "cart" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property.

Property or method "cartItems" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property

pages/cart.vue

<template>
<div>
    <v-container>
        <section>
           <h2 class="my-4">Your Cart</h2>
           <v-divider class="my-4"></v-divider>
           <h3>Total Amount: ${{ cart }}</h3>

           <CartItem
             v-for="item in cartItems"
             :key="item.productId"
             :prod-id="item.productId"
             :name="item.name"
             :image="item.image"
             :price="item.price"
             :qty="item.qty"
           ></CartItem>
        </section>
    </v-container>
   
</div>
</template>

<script>
import CartItem from '../components/CartItem'
import { mapGetters } from 'vuex'
export default {
  components: {
      CartItem,
      computed: {
           ...mapGetters('cart',['totalSum'])
    },
    cartItems(){
      return this.$store.getters['cart/products'];
    }
      }
  }

</script>

<style scoped>
h2{
    text-align: center;
}
h3{
    text-align: center;
}
</style>

./components/CartItem.vue

<template>
    <v-container class="my-5">
    <v-row>
        <v-col
        sm="6"
        md="4"
        >
          <v-card outlined>
            <v-img :src="image" height="200px" />
            <v-card-title> {{ name}} </v-card-title>
            <v-card-subtitle> ${{ price }}</v-card-subtitle>
            <v-card-subtitle> Quantity <strong>{{ qty }}</strong> </v-card-subtitle>
            <v-card-actions>
                <div>Total: ${{ itemTotal }}</div>
                          <v-btn @click="remove()" color="success" outlined >
                              <v-icon small left> add </v-icon>
                              Remove
                          </v-btn>
            </v-card-actions>
          </v-card>
        </v-col>
    </v-row>
  </v-container>
</template>

<script>
export default {
    props: ['prodId', 'name', 'image', 'price', 'qty'],

    computed: {
        itemTotal() {
            return( this.price * this.qty).toFixed(2);
        }
    },
    methods: {
        remove(){
            this.$store.dispatch('cart/removeFromCart', {productId: this.prodId})
        }
    }
}
</script>

store/modules/cart.js

export default {
    namespaced: true,
    state(){
        return{
            items: [],
            total: 0,
            qty: 0
        }
    },

    mutations: {
        addProductToCart(state, payload) {
            const productData = payload;
            const productInCartIndex = state.items.findIndex(
                (ci) => ci.productId === productData.id
            );

            if (productInCartIndex >= 0) {
                state.items[productInCartIndex].qty++;
            } else {
                const newItem = {
                    productId: productData.id,
                    title: productData.title,
                    image: productData.image,
                    price: productData.price,
                    qty: 1,
                };
                state.items.push(newItem);
            }
            state.qty++;
            state.total += productData.price;
        },

        removeProductFromCart(state, payload) {
            const prodId = payload.productId;
            const productInCartIndex = state.items.findIndex(
                (cartItem) => cartItem.productId === prodId
            );
            const prodData = state.items[productInCartIndex];
            state.items.splice(productInCartIndex, 1);
            state.qty -= prodData.qty;
            state.total -= prodData.price * prodData.qty;
        },
    },

    actions: {
        addToCart(context, payload) {
            const prodId = payload.id;
            const products = context.rootGetters['prods/products'];
            const product = products.find(prod => prod.id === prodId);
            context.commit('addProductToCart', product);
        },
        removeFromCart(context, payload) {
            context.commit('removeProductFromCart', payload);
        }
    },
    getters: {
        products(state) {
            return state.items;
        },
        totalSum(state) {
            return state.total;
        },
        quantity(state) {
            return state.qty;
        }
    }
}

Solution

  • The property cartItems should be added to the computed option like :

    export default {
      components: {
          CartItem,
         },
         computed: {
               ...mapGetters('cart',['totalSum']),
               cartItems(){
                return this.$store.getters['cart/products'];
              }
       
          }
      }