Jamie Bohanna
Jamie Bohanna

Reputation: 560

Unable to loop through Vue 3 Reactive Array prop (proxy)

The Task

I'm working on a marketplace of products. Each product has an ID and a bunch of information associated with each product.

There is a concept of packages of the products, which is simply a product that is a bundle of other products.

Within the GET PACKAGES response, there is an array of IDs which relate to the products inside this package. Else where on the page, I request a list of products, so I have the data I need already, I just need to connect the two data sets.

The task involves showing the packages in the UI, along with a description of each product (which is in the other response of GET PRODUCTS) which is connected by IDs between the two data sets.

Description of Setup

I have a parent component, which calls GET PRODUCTS and GET PACKAGES.

I pass the package down to a reusable Vue component to display basic information on that package in the UI. As well as this, I pass down ALL the products down to the component also, so that we can get the right product descriptions to display in the preview of the package UI.

The Problem

When passing down the list of products into the child component, I can console log the entire array of products perfectly fine, however the second I try to loop through them (either via MAP or FOREACH) nothing happens. No console log inside the loop; it's like the loop doesn't even run.

The Parent Component Code

<package 
    v-for="package in packages" 
    :key="package.id"
    :packages="package"
    :products="products"
></package>

// I get both sets of data in beforeOnMount and push it to the below variables
const packages = reactive<Array<Package>>([]);
const products = reactive<Array<Product>>([]);

The Child Component Code

props: {
    packages: Object as () => Package,
    products: Object as () => Array<Product>
}

setup(props) {
    const uiPackages= reactive<Array<IPackageDetails>>([]);
    const productData = props.products;

    // This console log's a Proxy, with the handler containing an array of objects perfectly fine.
    console.log(productData);

    if (productData) {

        // This console log's undefined
        console.log(productData[0]);

        productData.forEach((product) => {

            // This does NOTHING in console!
            console.log(product)
        }
    }
}

Console Log of the productData in the child component

Products with data blurred out due to NDA

Upvotes: 6

Views: 9604

Answers (1)

Dan
Dan

Reputation: 63099

When the child component initializes, the products prop is still an empty array. The reason you see data in the console is because the console updates itself when you click it, and by that time the parent's async request has completed.

This only happens with references, so you couldn't see the individual array item product[0] which has no reference when you log it.

Use a watch (or watchEffect) on the prop to wait for the items to be fetched:

setup(props) {
  const productData = props.products;

  watch(() => productData.length, () => {
    productData.forEach((item) => {
      console.log(item)
    })
  })
}

Alternatively, you could use a v-if in the parent:

<template v-if="packages.length && products.length">
  <package 
    v-for="package in packages" 
    :key="package.id"
    :packages="package"
    :products="products"
  ></package>
</template>

Upvotes: 7

Related Questions