I have a Vue composable that uses a Firebase onSnapshot
listener.
When data changes on that listener I want it to update a ref
named documentsArray
.
When I console.log the documentsArray
inside the onSnapshot
function it seems to be working because it contains an array of values. But when I console.log outside the onSnapshot
function the array is empty.
Why is this happening?
The console.log outside the onSnapshot
function should also contain the array of values.
Here is my composable (I am using TypeScript):
import { ref, Ref, watchEffect } from "vue";
import { projectFirestore } from "@/firebase/config";
import {
collection,
query,
orderBy,
onSnapshot,
DocumentData,
Timestamp,
} from "firebase/firestore";
interface Document {
id: string;
message: string;
name: string;
createdAt: Timestamp;
}
const getCollection = (
collectionString: string
): {
documentsArray: Ref<Document[] | null>;
error: Ref<string | null>;
} => {
const documentsArray = ref<Document[] | null>(null);
const error = ref<string | null>(null);
const colRef = collection(projectFirestore, collectionString);
const colRefOrdered = query(colRef, orderBy("createdAt"));
const unsubscribe = onSnapshot(
colRefOrdered,
(snap) => {
const results: Document[] = [];
snap.docs.forEach((doc: DocumentData) => {
doc.data().createdAt && //Ensures the server timestamp has been added
results.push({
...doc.data(),
id: doc.id,
});
});
documentsArray.value = results;
console.log("documentsArray.value inside snapshot", documentsArray.value); //<-- This works. It prints an array of documents.
error.value = null;
},
(err) => {
console.log(err.message);
documentsArray.value = null;
error.value = "could not fetch data";
}
);
watchEffect((onInvalidate) => {
onInvalidate(() => {
unsubscribe();
});
});
console.log("documentsArray.value outside snapshot", documentsArray.value); //<-- This does not work. It prints an empty array.
return { documentsArray, error };
};
export default getCollection;
CodePudding user response:
The code inside the onSnapshot
callback is run asynchronously (after running the code outside the callback), in order to see the changes outside function you've to create a watcher to see that changes:
import import { ref, Ref, watchEffect, watch } from "vue";
....
const unsubscribe = onSnapshot(
colRefOrdered,
(snap) => {
...
);
watch(documentsArray,(newVal,oldVal){
console.log("documentsArray.value outside snapshot", documentsArray.value);
},{deep:true})