Farr East
Farr East

Reputation: 67

Is it possible to render real-time changes in Firebase data within a Vue app?

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>

Upvotes: 0

Views: 2259

Answers (2)

Renaud Tarnec
Renaud Tarnec

Reputation: 83163

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>

Upvotes: 3

Bhushan Patil
Bhushan Patil

Reputation: 105

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

Upvotes: 0

Related Questions