Tips for incorporating async prop values into a Vue "v-for" component

I've been working with Vue and Firebase Firestore.

Currently, I have a dynamic list of individuals being displayed using the v-for directive. The length of this list is unknown as it is populated asynchronously from Firestore. Handling this part is simple since I can retrieve the data within an onMounted hook or set up a Firestore listener.

However, for each person in the v-for, I need to make another asynchronous call to Firestore to fetch their respective images (the image URLs are stored in a separate Firestore document). This particular aspect is posing a challenge for me on how to effectively manage it.

At present, all the images appear broken because the function getPersonImageById(person.id) performs asynchronously. As a result, it immediately returns undefined and then later retrieves the image URL. When attempting to load the prop value using await like so

<img :src="await getPersonImageById(person.id)" />
, I encounter the following error:

Error parsing JavaScript expression: 'await' is only allowed within async functions and at the top levels of modules. (1:1)

Here's a simplified version of my code snippet:

<template>
  <div v-for="(person, index) in people" :key="person.id">
    {{ person.name }}
    <img :src="getPersonImageById(person.id)" />
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue';

// Simulate async database call (i.e. Firestore)
const databaseAsyncFetch = async (data) => {
  await new Promise((resolve) => setTimeout(resolve, 2000));
  console.log(data);
  return data;
};

// Load the people data
const people = ref();
onMounted(async () => {
  people.value = await databaseAsyncFetch([
    { id: '1', name: 'John', fruit: 'Banana' },
    { id: '2', name: 'Mary', fruit: 'Apple' },
    { id: '3', name: 'Luke', fruit: 'Orange' },
  ]);
});

// Make another async call for each "person" inside the v-for to fetch the images
const getPersonImageById = async (id) => {
  await databaseAsyncFetch(
    'https://picsum.photos/100/100?random=' + id + '.jpg'
  );
};
</script>

You can also access the live example through this link: https://stackblitz.com/edit/vitejs-vite-ljqftl?file=src/App.vue

Answer №1

Instead of tying :src directly to a fetch call, it is recommended to make a follow-up fetch after the initial database fetch. Here is an example:

people.value = await databaseAsyncFetch([
    { id: '1', name: 'John', fruit: 'Banana' },
    { id: '2', name: 'Mary', fruit: 'Apple' },
    { id: '3', name: 'Luke', fruit: 'Orange' },
]);
people.value.forEach(person => { person.image = getPersonImageById(person.id) })

Subsequently, you can conditionally display the <img> based on whether or not person.image exists

<img v-if="person?.image" :src="person.image" />

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What's the deal with Firebase's ".info/connected" path?

The information provided below suggests that in order to activate ".info/connected", we must first read from the database. I am attempting to utilize ".info/connected" to verify if the user is connected to the internet. I check the boolean value returned ...

Determining the value of an object property by referencing another property

Upon running the code below, I encounter the following error message: Uncaught TypeError: Cannot read property 'theTests' of undefined $(document).ready(function() { var Example = {}; Example = { settings: { theTests: $(&apo ...

AngularJS is failing to recognize the onload event when loading a URL

I am currently working with the AngularJS Framework and I have encountered an issue. My directive only seems to work when the window is fully loaded. screensCreators.directive('createscreen', function () { return { restrict: "A", ...

Adjust the dimensions of the canvas without disrupting the existing artwork

I am currently working on a pixel art application where I am facing an issue with saving images from the canvas. The saved image appears small and pixelated when I try to resize it. I would like to resize the image to larger dimensions, but I am unsure of ...

the dropdown menu toggle is not working as expected

My dropdown icon is not appearing and the menu options are not functioning properly. Despite trying to use a script to display the text when an option is clicked, it doesn't seem to be working. It appears that the toggle functionality is not working ...

Fill out FormBuilder using data from a service within Angular2

I am working with an Angular2 model that I'm filling with data from a service. My goal is to use this model to update a form (created using FormBuilder) so that users can easily edit the information. Although my current approach works, I encounter er ...

How can I retrieve multiple fields using the Google Docs API in Node.js?

Is there a way to select multiple fields using the documents.get method? Currently, I am fetching the document like this: const doc = await docs.documents.get({ documentId: copiedFile.data.id, fields: 'body/content' }); which result ...

Stretch out single column content vertically in bootstrap for a uniform look

I've been struggling to make multiple buttons vertically stretch to fit the container, but I can't seem to remember how I achieved this in the past. I have experimented with various options outlined on https://getbootstrap.com/docs/4.0/utilities/ ...

In Angular 9, what is the best way to refresh a component's data field in the DOM without having to reinitialize it?

Exploring Angular 9 for the first time and facing a challenge. I have a feature in my application where users can enter a name, submit it via a POST HTTP request to store the name. In another component, there is a sub-header that displays a list of stored ...

Is there a way to create three duplicates of an item within an array loop?

Looking for assistance with repeating numbers in an array three times? Here's the example array: var array = [1,2,3,4,5,6,7,8,9,10...] To repeat each number three times in a loop and create a new array like this: var newarray = [1,1,1,2,2,2,3,3,3,4,4 ...

Replicating row with distinct values

I'm experiencing some difficulties with a particular issue. I currently have two tables as shown below: <table id="customFields1" class="table table-bordered table-hover additionalMargin alignment"> <thead> <tr> < ...

What is the purpose of having a boolean value if it is not going to be

I've noticed a pattern in several functions where the developer is returning a boolean value, despite it not being utilized: function getUserLoggedIn() { return true; } <a onclick="getUserLoggedIn();"><img src="/profile-image. ...

How to access the next nested property of an object in JavaScript

I've been working on a function to retrieve another property key from within the same object. Consider this example JSON: 'Test123': { 'Another Test': {}, 'Test some more': { 'Still testing?': ...

Incorporate a 1-second delay for each value in the stream using Bacon.js

Here is my code snippet: var bulk = array[1,2,3,4] var finalResult = Bacon .fromArray(bulk) .flatMap(isValInCouchDb) .filter(onesThatExist) .flatMap(putValInCouchDb) I want to introduce a 1-second delay after the filter operation before e ...

Vue js does not display the data stored in the image tag

Trying to display an image from a data object using Vue.js. Here is the code snippet: <a onclick="openModal()"><img src="{{product.productImageList[0]['name']}}"></a> However, in the DOM it appears as: <i ...

How can I make a Firebase query to sort in descending order using Swift?

Currently, I am utilizing Firebase along with Alamofire and AlamofireImage to cache my imageURL data and upload it to ImageShack. I have encountered some difficulties while attempting to create a descending query. Despite searching extensively, I have not ...

The Vuejs component fails to refresh when modifying a variable

I recently started learning Vue.js and managed to create a basic list/detail application. When I select the first item from the list, the detail component shows the correct information. However, switching to a different item does not update the detail comp ...

A Preload Link was discovered for Google Adsense, yet the browser failed to utilize it

Operating my Wordpress website [followmyinstagram.de] with Google Adsense implemented directly into the theme's code. No plugins are used for Adsense integration. Upon analyzing the page speed, Chrome displays a warning that a preload link for "" is ...

Transferring data to a web address

Utilizing a jax-rs endpoint, I am invoking a jsp page in the following manner. public String logout(@Context HttpServletRequest request,@DefaultValue("Empty Details") @QueryParam("logoutNotification") String logoutNotification, @Quer ...

What methods can be employed to maintain a consistent width for a multi-line span that aligns with the content?

Inside a div, I have 2 spans. When the content of the first span is short enough to fit on one line, the span's width matches the text content and positions the second span next to it. If the content of the first span is long and causes it to wrap, t ...