Finding the right way to cancel a Firestore stream within a Vue component using the onInvalidate callback

Currently, I am utilizing Vue 3 to develop a Firebase composable that is responsible for subscribing to an onSnapshot() stream.

I have been attempting to unsubscribe from this stream by invoking the returned unsubscribe() function within both watchEffect and onInvalidate. For more information on these functions, you can refer to the corresponding section in the Vue documentation.

By utilizing a console.log(), it has been confirmed that my watchEffect is indeed being triggered.

However, I seem unable to activate the second console.log() statement located inside the onInvalidate block. Consequently, uncertainty arises regarding whether the unsubscribe() function is being executed at all.

Given the code snippet provided below, why is it that the

console.log("unsubscribe fired");
never actually runs?

Is there an alternative method to ensure that I have successfully unsubscribed from the Firestore stream? Perhaps through logging in the Firebase dashboard or similar means?

Below is the TypeScript implementation of the Vue Firestore composable:

import { ref, reactive, watchEffect } from "vue";
import { projectFirestore } from "@/firebase/config";
import {
  query,
  orderBy,
  onSnapshot,
  DocumentData,
  collection,
} from "firebase/firestore";

const useCollection: any = (col: any) => {
  const documents = reactive<Record<string, unknown>[]>([]);
  const error = ref<string | null>(null);
  // references
  const collectionReference = collection(projectFirestore, col);
  const collectionOrdered = query(
    collectionReference,
    orderBy("createdAt", "desc")
  );
  // updates
  const unsubscribe = onSnapshot(
    collectionOrdered,
    (snapshot) => {
      snapshot.docs.forEach((doc: DocumentData) => {
        documents.push({ ...doc.data(), id: doc.id });
      });
      error.value = null;
      console.log(documents);
    },
    (err) => {
      console.log(err.message);
      documents.splice(0);
      error.value = err.message;
    }
  );
  watchEffect((onInvalidate) => {
    console.log("watchEffect fired"); //This fires
    onInvalidate(() => {
      unsubscribe();
      console.log("unsubscribe fired"); //This does not fire
    });
  });
  return { documents, error };
};

export default useCollection;

Answer №1

The reason for your callback not having any reactive object is because you lack one in the watchEffect function.

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

Steps to obtain the precise source code of a webpage

Is there a way to download the exact source code of a webpage? I have tried using the URL method and Jsoup method, but I am not getting the precise data as seen in the actual source code. For example: <input type="image" name="ctl00$dtlAlbums$ct ...

Continuously looping in Firefox on Android is the setInterval function

I have a brief section of JavaScript that I would like to use to check a server every few seconds and update the DOM. function updateCard() { var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState ...

Arranging numerous items based on date in JavaScript without prior knowledge

I'm facing an issue where I need to showcase JSON data containing events but want them sorted by time. The challenge is that the number of objects in the JSON can vary as users can keep adding more. Below is my code snippet demonstrating how the displ ...

Separating screens for logged in and logged out users in React Router with Firebase is not possible

I'm currently developing an application using React and Firebase. The app has a requirement for user authentication to access their own timeline. To achieve this, I have decided to split the app into LoggedIn screens and LoggedOut screens. In the App ...

Executing Promises in an Array through JavaScript

LIVE DEMO Here is a function provided: function isGood(number) { var defer = $q.defer(); $timeout(function() { if (<some condition on number>) { defer.resolve(); } else { defer.reject(); } }, 100); return defer.pro ...

SVG: Altering the dy attribute has no impact on the overall height of the bounding rectangle for the parent text

We are striving to align a group of tspan elements both vertically and horizontally. However, the parent container is not taking into consideration dy values. This lack of consideration is leading to alignment issues. If you adjust the dy values in this ...

The removal of the Lodash library from node modules is not occurring

In an effort to reduce bundle size, I made the decision to replace all lodash methods with core js methods in my Vuejs project. Despite attempting various npm uninstall commands such as: npm uninstall lodash npm uninstall lodash --save npm uninstall lodas ...

Display all files within every subdirectory located in a specified folder on Google Drive

Recently, I stumbled upon a script located at https://github.com/bluexm/snipets/blob/master/list%20Gdrive%20files%20and%20folders. The challenge I encountered was that the script was not capable of handling folders with identical names. As a result, I made ...

The results generated by the Google Maps API are consistently consistent

const request = require('request'); var geocodeAddress = (location) => { var encodedLocation = encodeURIComponent(location); request({ url: `http://www.mapquestapi.com/geocoding/v1/address?key=APIKey&location=${encodedLocation}` ...

Converting Persian calendar date to Gregorian in JavaScript

Looking for assistance in converting a date from 1379/10/02 to AD format, specifically to the date 2000/4/29 using the momentJs library. Any help with this task would be greatly appreciated. Thank you! ...

Utilizing Angular JS to Manage Controller Events

I am currently working on an application that requires saving a large amount of data in cascade, similar to a typical master-detail view. Within this view, there is a "Save All" Button which saves each row in an iteration. This process triggers jQuery cus ...

Browser with Node's https.Agent

In my npm package written in TypeScript, I utilize axios to make web requests. One of the endpoints requires certificate authentication, so I pass new https.Agent to axios to include the necessary certificates. Everything works perfectly when the module is ...

Error: Unspecified process.env property when using dotenv and node.js

I'm encountering an issue with the dotenv package. Here's the structure of my application folder: |_app_folder |_app.js |_password.env |_package.json Even though I have installed dotenv, the process.env variables are always u ...

Unlocking the Power of $http and Stream Fusion

I'm interested in accessing the public stream of App.net. However, when I attempt to retrieve it using a simple $http.get(), I only receive one response. $http .get('https://alpha-api.app.net/stream/0/posts/stream/global') .success(func ...

Error: The function Task.find is not recognized in Node.js

I've been encountering an issue with my model while connected to MongoDB and having a running server. The problem seems to be related to routing through the TaskController, but I'm not sure if it's due to the model or the find() function. I ...

Utilizing React Recharts to create personalized tooltips

In my current project, I am looking to create a custom tooltip to replace the default one in recharts. The default tooltip that I want to change is shown below: https://i.stack.imgur.com/TjTiL.png I would like the new custom tooltip to look like this: ...

Having trouble with JQuery toggle()? Need some assistance with fixing it?

My attempts to utilize JQuery toggle functionality have been unsuccessful. The sliding up and down animation is not smooth and instead happens very quickly. I aim to achieve a sliding effect in my code similar to this example (Please refer to Website Des ...

Create a social chat platform similar to Facebook by implementing a chat box feature with the help of AJAX, jQuery

Currently, I have developed a chat box with two persistent issues. Despite my attempts to rectify them, I am unable to find a solution. Below, I will outline my code, focusing on the HTML section where the chat box, chat text area, and chat members are dis ...

Installing Vue.js without using npm Alternate solution for setting up Vue

Is it possible to configure vue.js without using npm? I am currently unable to install npm due to certain circumstances. Will vue.js alone suffice or is there something essential that I am overlooking? P.S.: I am a beginner in vue.js and do not want to en ...

Animating CSS Pixel Fragments

After applying a simple CSS animation that moves size and box shadows from one side of the screen to the other, I am noticing residual pixel fragments left behind. To see this issue in action on Chrome 66, check out the Code Pen: https://i.sstatic.net/Gl ...