0

I am using Firebase for Authentication and a database within a Vue app. The component I am working on listens for changes within a 'friends' collection for a specific user.

I would simply like to display the list of friends while reflecting changes from the database in real-time.

So far, I have taken two approaches and both result in the same problem of successfully capturing the changes, but being unable to display the change within the dom.

Approach 1

Within the created() function I add my listener using the .onSnapshot() function. This successfully captures the changes in the database. However, if I set this.friendsto the updated values the screen does not change.

Approach 2

Using Vuex to load the friends list. I created a watch function for the store which successfully tracks the changes. But changing the this.friendswithin this watch function is also not updating the screen.

Reactivity for simpler variables is working as expected.

<template>
  <v-container fluid>
    {{ friends }}
  </v-container>
</template>

<script>
import db from '@/firebase/firestore'
import firebase from 'firebase'

export default {
  name: 'Test',
  data() {
    return {
      friends: []
    }
  },
  created() {
    let firebaseUser = firebase.auth().currentUser
    let ref = db.collection('users')
    ref.where('user_id', '==', firebaseUser.uid).limit(1).get()
    .then( snapshot => {
      if (snapshot.docs[0].data()) {
        db.collection("users").doc(snapshot.docs[0].id)
        .onSnapshot(function(doc) {
          let user = doc.data()
          console.log('friends', user.friends) // outputs correctly
          this.friends = user.friends // does not update dom
        })
      }
    })
  },
}
</script>

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Farr East
  • 67
  • 8

2 Answers2

3

You may set up a listener as follows:

<template>
   <v-container fluid>
      {{ friend }}
   </v-container>
</template>

<script>
import db from '@/firebase/firestore'
import firebase from 'firebase'

export default {
  name: "Test",
  data() {
    return {
      friend: null
    };
  },
  created() {
    const firebaseUser = firebase.auth().currentUser
    const ref = db.collection('users')

    ref
      .where('user_id', '==', firebaseUser.uid)
      .limit(1)
      .onSnapshot(querySnapshot => {
         let f = querySnapshot.docs[0].data();
         f.id = querySnapshot.docs[0].id;
         this.friend = f;
      });
  }
};
</script>

<style>
</style>

FYI, if you want to remove the .limit(1) and display all the friends, do as follows:

<template>
  <v-container fluid>
    <template v-for="f in friends">
      <div>{{ f.id }}</div>
    </template>
  </v-container>
</template>

<script>
import db from '@/firebase/firestore'
import firebase from 'firebase'

export default {
  name: "Test",
  data() {
    return {
      friends: []
    };
  },
  created() {
    const firebaseUser = firebase.auth().currentUser
    const ref = db.collection('users')

    ref
      .where('user_id', '==', firebaseUser.uid)
      .onSnapshot(querySnapshot => {
        var fArray = [];
        querySnapshot.forEach(doc => {
          let f = doc.data();
          f.id = doc.id;
          fArray.push(f);
        });
        this.friends = fArray;
      });
  }
};
</script>

<style>
</style>
Renaud Tarnec
  • 79,263
  • 10
  • 95
  • 121
  • 1
    Thanks @renaud-tarnec your solution has worked. It seems that my approach had a second nested async call which affected reactivity. By simplifying the call it updated as expected. Huge thanks for this! – Farr East Apr 03 '19 at 15:45
0

Are You using Vuex or not if you are using Vuex then first you have to import getters in Computed Property otherwise if you are not using Vuex you have to watch that the data which are changing . You have to watch Computed Property Remember component will re-render only of data property change if data change then vue know that ok something change in this component and it will re-render that component You have to follow this below answer for you solution Watching Computed Property in Vue

Bhushan Patil
  • 105
  • 2
  • 8
  • thanks for your input. I did attempt to use Vuex in this manner and it worked when outputting to the console but did not trigger a re-render. Based on renaud-tarnec code it seems that nesting the firebase calls like I did was causing a reactivity problem. Thanks for your input! – Farr East Apr 03 '19 at 15:48