#Async/Await Nuxt - Composable

1 messages · Page 1 of 1 (latest)

noble linden
#

I'll start by setting the scene and sharing that I am new to both Typescript and Nuxt.

So, I'm trying hook up Airtable with Nuxt and I am making good progress. I created a composable and I am successfully calling the Airtable API. Looping through the received data is going to plan too.

Problem: I am calling the composable from my index.vue "products" page but I'm not received the data from the composable. It seems that I am not doing the async or await properly?

index.vue

`<script setup>
const airtable = useAirtable()
let dataProducts = await airtable.getAirtableData()

console.log('Page Products shows first with dataProducts Undefined', dataProducts)

</script>
<template>
<div>
My Products Page
</div>
</template>`

I am not sure if a stackblotz share helps without me sharing my API access token:
https://stackblitz.com/edit/nuxt-airtable?file=pages%2Fproducts%2Findex.vue,composables%2FuseAirtable.ts

StackBlitz

A Nuxt.js project based on airtable, sass, @nuxt/devtools, @types/node, autoprefixer, nuxt, postcss and tailwindcss

worn adder
#

Hello, would be good if we can narrow down the issue to either Vue Setup or the Airtable script.

  1. Script: Does the fetch happen and does the response look good inside getAirtableData() before it reaches the component? (If you log inside)
  2. Vue: Stub out the function with a setTimeout promise return and dummy data, and see if that one shows successfully

It's good to understand where the problem is but here are some other suggestions:

Nuxt

useAsyncData provides access to data that resolves asynchronously.

low timber
#

Correct. Your function is async but inside you don’t await.

noble linden
noble linden
worn adder
#
  1. Make let dataProducts = [] as productRecord[]; reactive using a ref
  2. Remove the done function and return the promise directly
const getAirtableData = async () =>
    baseAirtable('Products')

return the reactive dataProducts in the component
3. show loading if dataProducts is empty (ideally, you return loading and error from composable, and even run function on calling and only return the ref)

noble linden
# worn adder 1. Make `let dataProducts = [] as productRecord[];` reactive using a ref 2. Re...

I am a bit unsure how to do follow your instructions. 1. I just looked up ref() and this is also new to me. 2. return promise directly? I also started looking at useFetch instead of using the Airtable.js. Maybe that's a btter approach. I folowed the code examples on Airtable and the API works fine, I just struggle to get the data from my composanle useAirtable.ts to my products/index.vue. tbh, I am not sure why a composable should be used for this either.

noble linden
worn adder
#

Good start.

  1. Try logging dataProducts inside a watchEffect, because now its reactive and will update. It will be an empty array at the start.
  2. Typing a ref can be done using a generic. ref<ProductRecord[]>([])
  3. Are you pushing to the ref array correctly?
noble linden
# worn adder Good start. 1. Try logging dataProducts inside a watchEffect, because now its re...

I seem to have done something wrong with the "ref":

let dataProducts = ref<productRecord[]>([])

The push did indeed not work:

"Property 'push' does not exist on type 'Ref<{ productcode: string; stylecode: string; collectioncode: string; style: string; category: string; teaser: string; description: string; careinstructions: string; rrp: string; images: { filename: string; url: string; }[]; }[]>'.ts(2339):

worn adder
#

Are you referencing the ref using dataProducts.value

noble linden
#

With your tips and some help from ChatGPT I am almost there.

#

The console log now shows that the data is fetching and returned to my products/index.vue

#

the console shows this:
Fetching products...                Products fetched from Airtable: 51                                                                                                   Fetched products: [                                                                                                                             {     productcode: 'kk-ss23-A001',     stylecode: 'A',     collectioncode: 'kk-ss23',     style: 'Small Logo',     category: 'Polos',     teaser: "Introducing ...",     description: '',     careinstructions: '',     rrp: 69.95,     images: [ [Object], [Object], [Object], [Object], [Object] ]   }, ... the rest of the 51 products   {     productcode: 'kk-ss23-T001',     stylecode: 'T',     collectioncode: 'kk-ss23',     style: 'Long Sleeve',     category: 'Shirts',     teaser: '',     description: '',     careinstructions: '',     rrp: 99.95,     images: [ [Object], [Object] ]   } ] Products fetched successfully: 51

#

So it;s not quite there yet

#

it doesn't look like an array of products

#

well, the "productsData.value.length" works in the script section but not in the template part of the index.vue

low timber
#

In the template it should be written as productData.length because reactive variables are unwrapped and .value is not needed.

#

Also, your screenshot shows .values which is invalid

noble linden
#

I just added some console logs and I am very confused.

products/index.vue | Fetching products... useAirtable.ts | Fetching products from Airtable... useAirtable.ts | Products fetched from Airtable: 51 products/index.vue | Products fetched successfully: 51

#

yet the template shows
Products: 0
No products found.

noble linden
#

I have a feeling the template section happens before the data is being fetched

worn adder
#

Yes, template sections happens before, but its reactive so it should update as soon as productData gets updated 🙂