Home > Enterprise >  vue 3 unable to access data object in method
vue 3 unable to access data object in method

Time:11-29

I'm getting an error with my vue3 app. I'm trying to make a function in the methods{} block which hits dynamodb, and creates a listmap of data, which I want to pass to a child component with props. I am calling the function that communicates with dynamoDB in the created(){} block.

I'm not quite at the part of passing the data. Instead, I'm getting the following errors when trying to populate the productsData object in the data(){} block.

I'm setting the type of my products prop to be an interface I defined.

I am then casting that productsData data object to the products prop type.

For some reason, I am unable to push() maps to the this.productsData object as it is undefined.

Here's the error

[Vue warn]: Missing required prop: "products" 
  at <Home onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< undefined > > 
  at <RouterView> 
  at <App> runtime-core.esm-bundler.js:6589
TypeError: _this.productsData is undefined

html:

<template>
  <div class="home">
    <HelloWorld :key="key" :products="products" />
  </div>
</template>

typescript code:

<script lang="ts">
import { defineComponent, PropType } from "vue";
import { DynamoDBClient, QueryCommand } from "@aws-sdk/client-dynamodb";
import { fromCognitoIdentityPool } from "@aws-sdk/credential-providers";
import DBResponse from "@/interfaces/DBResponse";
import HelloWorld from "@/components/HelloWorld.vue";

export default defineComponent({
  name: "Home",
  components: {
    HelloWorld,
  },
  props: {
    products: {
      type: Object as PropType<DBResponse[]>,
      required: true,
    },
  },
  data() {
    return {
      key: 0,
      productsData: this.products,
    };
  },
  methods: {
    forceRerender() {
      this.key  = 1;
    },
    async getProductData() {
      const region = process.env.VUE_APP_AWS_REGION as string;
      const clientDynamoDB = new DynamoDBClient({
        region,
        credentials: fromCognitoIdentityPool({
          identityPoolId: process.env.VUE_APP_IDENTITY_POOL_ID as string,
          accountId: process.env.VUE_APP_AWS_ACCOUNT_ID,
          clientConfig: { region },
        }),
      });
      const query_input = {
        TableName: process.env.VUE_APP_TABLE_NAME,
        IndexName: "GSI1",
        KeyConditionExpression: "SK = :sort_key and DK1 = :data_key",
        ExpressionAttributeValues: {
          ":sort_key": { S: "PRODUCT#BLEND" },
          ":data_key": { S: "listed" },
        },
        Select: "ALL_ATTRIBUTES",
      };
      const command = new QueryCommand(query_input);
      try {
        const results = await clientDynamoDB.send(command);
        const items = results.Items;
        const cloudfrontHost = process.env.VUE_APP_CLOUDFRONT_HOST as string;
        if (items) {
          for (const key in items) {
            const item = items[key];
            this.productsData.push({
              id: item.PK.S?.split("PRODUCT#")[1],
              name: item.Name.S,
              src: cloudfrontHost.concat(
                "/products/assets/",
                item.PK.S?.split("PRODUCT#")[1] as string,
                ".png"
              ),
              description: item.Description.S,
              price: item.Price.S,
            });
          }
        }
      } catch (err) {
        console.error(err);
      }
      console.log(this.productsData);
      this.forceRerender();
    },
  },
  created() {
    this.getProductData();
  },
});
</script>

CodePudding user response:

productsData is initialized to products, but the products prop is missing (as seen in the error message), so both are undefined.

Based on your comment, you actually don't need the products prop at all. You're setting up productsData[] by pushing data into it in getProductsData() (called from created() hook), so the products prop does not even come into play.

The solution seems to be to remove the products prop, and initialize productsData to an empty array with a type assertion (as DBResponse[]):

export default defineComponent({
  //props: {
  //  products: {
  //    type: Object as PropType<DBResponse[]>,
  //    required: true,
  //  },
  //},
  data() {
    return {
      //productsData: this.products,
      productsData: [] as DBResponse[]
    };
  },
})
  • Related