Can Firebase data be updated in real-time in a Vue app?

Utilizing Firebase for Authentication and integrating a database into a Vue app, my current task involves monitoring changes within a 'friends' collection specific to a user.

The objective is to seamlessly display the list of friends while reflecting real-time updates from the database.

I've experimented with two different approaches, both successful in capturing the changes but encountering an issue when it comes to updating the DOM.

Strategy 1

Incorporating the .onSnapshot() function within the created() method, I can effectively capture database modifications. However, setting this.friends to the updated values does not result in a visual change on the screen.

Strategy 2

Implementing Vuex to load the friends list, I established a watch function for the store, which adeptly tracks changes. Despite this, altering this.friends inside the watch function also fails to update the displayed content.

Reactivity works as expected for simpler variables.

<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>

Answer №1

To establish a listener, follow these steps:

<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>

Just a heads up, if you wish to eliminate the .limit(1) and exhibit all the friends, do the following:

<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>

Answer №2

When working with Vuex, it is important to first import getters into the Computed Property. However, if you are not using Vuex, you need to watch for changes in the data. Remember, the component will only re-render if there is a change in the data property. Vue will recognize this change and update the component accordingly. To find more information on watching Computed Property in Vue, refer to this helpful answer

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The Angular bootstrap datetimepicker doesn't support disabling past dates

Has anyone successfully disabled past dates on an angular bootstrap datetimepicker before? I've tried using the date-disabled attribute, but I can't seem to get it to work. <datetimepicker class="calendar-format" data-ng-model ...

"Unlocking the Dialog Box: A Step-by-Step Guide to Programatically Opening Material UI Dialog

Typically, Material UI's Dialog is used as shown below, following the documentation: export default function AlertDialog() { const [open, setOpen] = React.useState(false); const handleClickOpen = () => setOpen(true); const handleClose = () =& ...

The connection of props in VueJS

Looking to establish linking dependencies between props in a VueJS component? Specifically, I want to set up a scenario where if one prop is present, another prop becomes required, but unnecessary if the first prop is absent. props: { url: { type ...

The error message you are encountering is: "Error: Unable to find function axios

Can't figure out why I'm encountering this error message: TypeError: axios.get is not functioning properly 4 | 5 | export const getTotalPayout = async (userId: string) => { > 6 | const response = await axios.get(`${endpoint}ge ...

Is there a way for me to move a user from one room to another room?

My friend and I both have our own rooms in a session. When I want to send him a message, I need to switch his room to the same one where I am. This is the code snippet for creating my own room with static sessions: socket.on('chat-in', function ...

Error: Attempting to access a property called 'name' on an undefined variable leads to a TypeError

I am a beginner with MongodB and nodejs. I have successfully implemented the GET method, which returns an empty array. However, when I tried to use POST in Postman for "categories," I encountered this error message: ExpressJS categories route app.js Err ...

What is the best method for eliminating a character from all elements in jQuery classes?

I am working on an Angular 4 app where every .inner-page class in a html element includes a "/". For instance: <div _ngcontent-c0="" class="inner-page /login"> <div _ngcontent-c0="" class="inner-page /register"> I need to eliminate the "/" c ...

Discovering the method to retrieve the information of the selected item in AngularJS

My table is using the ng-repeat in the <tr> element to load content dynamically from a JSON file. Each row has a unique ID in the table. I need a way to access the inner HTML of the respective row's ID column when it is clicked. Is there a solut ...

What are the ways in which Angular can offer assistance to Internet Explorer 9?

The news is out - the Angular team has just announced their support for Internet Explorer 9! This revelation has left me wondering, how is it even possible? Currently, I am an avid user of AngularJS and have dedicated time to studying its ins and outs. Fr ...

What is the functionality of client-side applications?

I am new to web development and my programming background is primarily focused on algorithms and creating visualization tools using local Windows forms. I often distribute these tools via email as compiled exe files (C++ or C# win form) to my math students ...

Learn how to retrieve JSON data from the Yahoo Finance REST API using Angular 2

Currently, I am in the process of developing an application that needs to fetch data from the Yahoo Finance REST API. To retrieve a table for the symbol "GOOG," I have implemented the following code: export class ActService{ act = []; url = 'http ...

Jasmine is having trouble scrolling the window using executeScript

I usually use the following command: browser.driver.executeScript('window.scrollTo(0,1600);'); However, this command is no longer working. No errors are showing in the console, making it difficult to troubleshoot. Interestingly, the same scri ...

Incorporating React components into your current Django project

My goal is to enhance the interactivity of a specific part of my Django website by incorporating React components into the template HTML file. Instead of replacing the entire template with React, I want to focus on integrating React for its ease in handlin ...

Implementing a Collapse and Expand All feature within an Accordion Component

Hey there! I've been attempting to implement a Collapse All feature on my accordion but am having trouble figuring it out. The resource I've been referencing is this one. I've searched around and noticed that this accordion setup is a bit d ...

Trigger an Ajax form submission upon a change occurring

My Ajax form needs to be submitted as soon as the user selects an image, but I'm encountering an issue with the form not submitting. Any guidance on resolving this problem would be greatly appreciated. -- Below is the form --- <form id="bgimagefo ...

Is there a way to retrieve the Marker that is being dragged when the event handler has already been bound?

How can I identify the Marker that is being dragged when the handler is a bound function? Take a look at this snippet from my react component: constructor() { this.handleMarkerMove = this.handleMarkerMove.bind(this); } createMarker() { const marker ...

What methods could I use to prevent the WYSIWYG buttons from automatically linking?

I've been working on creating an editor but I'm facing a small issue. Every time I click on a button (such as bold or italic), it follows a link instead of performing the desired action. Here's a snippet of what I've tried so far: fu ...

The error handler function is missing in Zepto's $.post method

When I was using Zepto instead of jQuery, I noticed that while the $.ajax method has an error handler, other methods like $.post and $.get do not. Do you know why this is the case? Function Signature $.post(url, [data], function(data, status, xhr){ ... }, ...

Navigating through an array of objects with Node.js

Recently, I integrated the ChartJS library into my Node web app to visualize data. The following is nested in a script tag on an EJS template page: <script> let playerStatChart = new Chart(myChart, { type: 'bar', data: { la ...

Binding data to an MVC grid component

I am working with asp.net mvc3.0 razor framework and using an html Table to populate data from ViewBag based on the selected option in a dropdownlist. public ActionResult Index(GetFileName fn) { .... ViewBag.Grid1Data = dt; return View(); } Initially, th ...