Search code examples
javascriptfirebasevue.jsgoogle-cloud-firestorevuex

Iterate through list of document uids and create listeners in Firestore


In my Vuex store, I have an action that takes a list of uids of followed users from the current user's Firestore UserDataCollection document, iterates through them, and produces the data for each document to be shown on the UI. It works fine using .get(), but I'm trying to convert it to .onSnapshot() so that I can get real-time updates.

I have been totally unsuccessful trying to use .onSnapshot(), as I can't find any references online or in the Firebase docs on how to implement this after mapping through the array of uids.

I tried removing the promises, since onSnapshot doesn't seem to work with promises, and replaced the .get() with .onSnapshot(), but that didn't work.

Does anyone know the correct way to implement the Firestore .onSnapshot() listener given the code below?

getCircle({state, commit}) {
      const circle = state.userProfile.circle
      let promises = circle.map(u => userDataCollection.doc(u).get())
      
        return Promise.all(promises)

        .then(querySnapShot => {
          let circleData = []
          if (querySnapShot.empty) {
            console.log("empty")
          } else {
            querySnapShot.forEach(doc => {
              let item = doc.data()
              circleData.push(item)
             }
            )
          }
          commit('setUserCircle', circleData)
        })
   },

Edit based on response

I added .onSnapshot within the forEach as shown in the code below. In vue devtools it's showing the correct number of data entries in my Vuex store, however they are all undefined.

getCircle({state, commit}) {
  const circle = state.userProfile.circle
  let promises = circle.map(u => userDataCollection.doc(u).get())
  
    return Promise.all(promises)

    .then(querySnapShot => {
      let circleData = []
      if (querySnapShot.empty) {
        console.log("empty")
      } else {
        querySnapShot.forEach(x => {
          let itemId = x.data().uid
          userDataCollection.doc(itemId)
            .onSnapshot((doc) => {
              let item = doc.data()
              console.log(doc.data())
              circleData.push(item)
          })   
          }
        )
      }
      commit('setUserCircle', circleData)
    })

},


Solution

  • Thank you everyone for the help. The solution that worked was to remove the .map and Promise and used an 'in' query. Code shown below:

     getCircle({state, commit}) {
       const circle = state.userProfile.circle
    
       userDataCollection.where('__name__', 'in', circle).onSnapshot(querySnapShot => {
        var circleData = []
        querySnapShot.forEach(doc => {
          let item = doc.data()
          circleData.push(item)
          commit('setUserCircle', circleData)
        })
      })
    },