Home > database >  Vue3: How to wait for full array before rendering component?
Vue3: How to wait for full array before rendering component?

Time:10-14

In a Vue 3 app, I need to use a modal component directly on page load. The problem is that this component needs to wait for a specific array to be populated in Vuex, before rendering to the DOM:

  <!--begin::Edit profile tag list -->
  <Modal1
    v-if="$store.state.teammembers.length > 0"
    whichModal="editProfileTags"
    title="Edit tag list"
    buttonText=""
  ></Modal1>
  <!--end::Edit profile tag list-->

In the code above, I am only checking if the array exists and has at least one item. But how can I make sure all existing items have been stored in the array before render?

I don't know if using props could be a solution, but I would like to avoid it as I find it much easier to work only with centrally stored data (many sibling components).

To get the data in the array in the first place, I am using a Firestore request with a realtime listener:

//Get teammembers
const qTeammembers = query(collection(db, "users"), where("teamid", "==", store.state.userData.teamid));
unsubToTeamMembers = onSnapshot(qTeammembers, (teammembersSnap) => {
    store.state.teammembers = []
    teammembersSnap.docs.forEach((doc9) => {
        let teammember = doc9.data()
        teammember.docid = doc9.id

        //Create an array of team members
        store.state.teammembers.push(teammember)

    })
})

As I am using an onSnapshot I can't follow up with a .then() method once everything has been fetched.

CodePudding user response:

How about setting a temporary variable (teamMembers) and push each item to that variable instead. Then set it to state afterwards, when all items has been pushed.

const qTeammembers = query(collection(db, "users"), where("teamid", "==", store.state.userData.teamid));
unsubToTeamMembers = onSnapshot(qTeammembers, (teammembersSnap) => {
    store.state.teammembers = []
    const teamMembers = []
    teammembersSnap.docs.forEach((doc9) => {
        let teammember = doc9.data()
        teammember.docid = doc9.id

        // Create an array of team members
        teamMembers.push(teammember)
    })
    store.state.teammembers = teamMembers
})

CodePudding user response:

I'm not sure, are you using Vue 3 but according to your comment about <suspense> here is an example how you can use asynchronous observer onSnapshot() in a Promise.

dishList.vue

<template>
    <ul v-if="data.length">
        <li v-for="item in data" :key="item">{{ item }}</li>
    </ul>
</template>

<script setup lang="ts">
import { onSnapshot, collection, getFirestore } from '@firebase/firestore'
const data = ref([])

await new Promise(resolve => {
    return onSnapshot(collection(getFirestore(), 'dishes'), snap => {
        if (!snap.empty) {
            snap.forEach(docSnap => {
                data.value.push(docSnap.data())
            })
            setTimeout(() => resolve('done'), 500)
        }
    })
})
</script>

app.vue

<template>
   <Suspense>
      <dishList></dishList>
      <template #fallback>Loding Data...</template>
   </Suspense>
</template>

If you want more accurate answer to your question you need to provide more code whole components not just little snippet of them.

  • Related