1

I am trying to add the items passed from the props to a ref property using a vue-composition API. But, I don't know why the items are not added to the array. Maybe I am using the spread operator in a wrong way or my implementation is wrong but the item is not added.

vue-composition method is in a different file and it is used across the component.

I am passing the props to a product component in this way:

 <product
    :id="12345667"
    title="Pampers 9x Sensitive Baby Wet Wipes Filler, 576 Diaper Wipes"
    price="14.59"
    :rating="4"
    image="https://images-na.ssl-images-amazon.com/images/I/41Yo4bc2uiL._AC_US160_.jpg"
  >
  </product>

Similarly, the product component is setup as:

   <template>

    <div class="product">
          <button type="button" @click="addToCart(item)">Add to Basket</button>
    </div>

   </template>

   <script>
    import { useCart } from "../js/ShoppingCart";
    
    export default {
      setup(props) {
        let item = props;
    
        const { addToCart } = useCart();
    
        return { item, addToCart };
      },
      props: {
        id: Number,
        title: String,
        image: String,
        price: String,
        rating: Number,
      }
    };
    </script>

ShoppingCart.js where I am using the @vue-composition-api

import { ref } from "@vue/composition-api";
export function useCart() {
  let basket = ref([]);
  const addToCart = async (item) => {
    // eslint-disable-next-line no-debugger
    debugger;
    return {
      ...basket,
      item,
    };
  };
  console.log(JSON.stringify(basket));
  return { basket, addToCart };
}

I don't know where do I did wrong, the basket array is always empty while calling from different components.

Updated Question:

<template>
  <div class="home">
    <img
      class="home__image"
      src="https://images-na.ssl-images-amazon.com/images/G/01/AmazonExports/Fuji/2020/May/Hero/Fuji_TallHero_45M_es_US_2x._CB432534552_.jpg"
    />

    <div class="home__row">
      <product
        :id="12345667"
        title="Pampers 9x Sensitive Baby Wet Wipes Filler, 576 Diaper Wipes"
        price="14.59"
        :rating="4"
        image="https://images-na.ssl-images-amazon.com/images/I/41Yo4bc2uiL._AC_US160_.jpg"
      >
      </product>
      <product
        :id="12345667"
        title="Pampers 9x Sensitive Baby Wet Wipes Filler, 576 Diaper Wipes"
        price="14.59"
        :rating="4"
        image="https://images-na.ssl-images-amazon.com/images/I/41Yo4bc2uiL._AC_US160_.jpg"
      >
      </product>
      {{ basket }}
      basket length {{ basket.value ? basket.value.length : 0 }}
    </div>
  </div>
</template>
<script>
// @ is an alias to /src
import Product from "@/components/Product.vue";
import { useCart } from "../js/ShoppingCart";
export default {
  setup() {
    const { basket } = useCart();
    return { basket };
  },

  name: "Home",
  components: {
    Product,
  },
};
</script>
0

1 Answer 1

8

I don't see any place in there where you're actually updating the basket array.

Also, you're not capturing the returned value, so you can remove it, and you may not need async function

You should be able to use basket.value.push(item);

ShoppingCart.js

import { ref } from "@vue/composition-api";
export function useCart() {
  let basket = ref([]);
  const addToCart = (item) => {
    basket.value.push(item);
  };
  return { basket, addToCart };
}

or basket.push(item); if you switch ref for reactive

ShoppingCart.js

import { reactive } from "@vue/composition-api";
export function useCart() {
  let basket = reactive([]);
  const addToCart = (item) => {
    basket.push(item);
  };
  return { basket, addToCart };
}

Update #1:

in your template you're using {{ basket.value ? basket.value.length : 0 }}

One problem is that value is resolved through the template, so you should not use it in the template.


Update #2:

Looks like you're trying to use useCart as a global store. The reason that it's not working is that you are creating a new store every time you instantiate useCart

if you run it like this, it will create a new instance:

import { ref } from "@vue/composition-api";
export function useCart() {
  let basket = ref([]); // <--- new store, local to function
  const addToCart = (item) => {
    basket.value.push(item);
  };
  return { basket, addToCart };
}

but if you update it to this

import { ref } from "@vue/composition-api";
let basket = ref([]); // <--- same store, global
export function useCart() {
  const addToCart = (item) => {
    basket.value.push(item);
  };
  return { basket, addToCart };
}

useCart() will now reuse the same ref

Update #3:

Haven't tested, but you could try this as-well to get around the error in Vue2

import { ref, isRef } from "@vue/composition-api";
let basket;
export function useCart() {
  if (! isRef(basket)) basket = ref([]);
  const addToCart = (item) => {
    basket.value.push(item);
  };
  return { basket, addToCart };
}
Sign up to request clarification or add additional context in comments.

9 Comments

isn't return { ...basket, item, }; pushing and returning the basket array?
it just returns an object with basket flattened, followed by the item
you could probably remove it (unless you need the updated values immediately, but that doesn't look like the case based on your component template)
i am using basket length {{ basket.value ? basket.value.length : 0 }} to display the length of the array. but the count is always 0. What could be wrong?
in the template you don't need value. ` {{ basket.value ? basket.value.length : 0 }}` will always return 0, because basket.value is undefined(falsy)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.