Search code examples
javascriptfirebasevue.jsgoogle-cloud-firestorevuefire

vuefire: how to declare a reactive collection using usecollection() before the collection path is known?


i'm very new at Vue+Vuefire. I'm trying to get a collection of documents (recipes) linked to a user's ID (a subcollection in the user doc.

The firestore path to the collection is something like users/${user.uid}/recipes. My problem is that I get an error when first declaring my collection recipesStore = usecollection(...) as there is no defined path at the initial step. During a refresh I usually get an error in the console:

error message

I guess this error is happening when the path / userID is not known yet.

In my code I only get the user ID once the user has signed up, but I'm declaring reactive collections as below, starting with an empty object and then updating at sign-in with the right path pointing to the user's collection, through the function updateCollectionWithUser(user).

export const recipesCollection = ref({})
export const recipesStore = useCollection(recipesCollection, {wait: true})

export const updateCollectionWithUser = async (user) => {

    recipesCollection.value = collection(db, `users/${user.uid}/recipes`)

}

It does not seem to be blocking, but I feel this error is a symptom of some bigger issue in my code. Usually, when signing in, I don't see the error in the console. But if I refresh the page, I see the error in the console, while still able to load the collection.

Is the issue linked to vuefire not being able to work with empty path, or is it linked to management of Promises (which is very obscure to me). What's the best way to start with an unknown path to a collection?


Solution

  • Since user is reactive, you need to build your query using a reactive observer that actively tracks the user state and fetches data accordingly.

    Add the VueFireAuth module to the VueFire plugin:

    // ./main.js
    import { VueFire, VueFireAuth } from 'vuefire'
    app.use(VueFire, {
      firebaseApp: createFirebaseApp(),
      modules: [
        // ... other modules
        VueFireAuth(),
      ],
    })
    
    
      // get the current user as a reactive variable 
      // with the useCurrentUser() composable
      import { useCurrentUser } from 'vuefire'
    
      const user = useCurrentUser();
    
      const recipeRef = computed(() => {
        return getDocs(collection(db, `users/${user.value?.uid}/recipes`));    
      })
    
      // userRecipes will always be in sync with the data source
      const userRecipes = useCollection(recipeRef); 
    
    

    You can refer to VueFire's docs for more details https://vuefire.vuejs.org/guide/auth.html