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.