firebasevue.jsgoogle-cloud-firestorevueuse

How to reference a VueUse useFirestore ref in another useFirestore?


I'm trying to use the VueUse useFirestore() wrapper.

It returns a ref that is in sync with a Firestore document.

Currently I can use it to get and display a users doc.

But now I need to get and display a websites doc by referencing a currentWebsiteId field from the users doc.

When I try to do that, nothing is displayed. There are no errors in the console either.

This is what my code looks like:

<template>
  <div>{{ user }}</div> 
  <div>{{ website }}</div>
</template>

<script setup lang="ts">
import { useAuth } from '@vueuse/firebase/useAuth';
import { useFirestore } from '@vueuse/firebase/useFirestore';
import { doc } from 'firebase/firestore';
import { auth, db } from 'src/config/firebase';
import { User, Website } from 'src/types';

const { user: authUser } = useAuth(auth);

const userDocRef = doc(db, `users/${authUser.value?.uid}`);
const user = useFirestore<User>(userDocRef);

const websiteDocRef = doc(db, `websites/${user.value?.currentWebsiteId}`);
const website = useFirestore<Website>(websiteDocRef);
</script>

Since useFirestore() is asynchronous it will initially return undefined before shortly after returning the actual Firestore document.

I thought this could be the issue, so I tried using a watch to get around that like so:

let website = ref();
watch(user, () => {
  const websiteDocRef = doc(db, `websites/${user.value?.currentWebsiteId}`);
  website = useFirestore<Website>(websiteDocRef);
});

But that also has the same problem. Nothing is nothing is displayed, and there are no errors in the console either.


Solution

  • As commented by @EstusFlask, the docs show that it needs to be wrapped in a computed ref.

    This is because computed gets recalculated when any of it's ref values change.

    Therefore websiteDocRef becomes this:

    const websiteDocRef = computed(() =>
      doc(db, `websites/${user.value?.currentWebsiteId}`)
    );
    

    Here is the full code:

    <template>
      <div>{{ user }}</div> 
      <div>{{ website }}</div>
    </template>
    
    <script setup lang="ts">
    import { useAuth } from '@vueuse/firebase/useAuth';
    import { useFirestore } from '@vueuse/firebase/useFirestore';
    import { doc } from 'firebase/firestore';
    import { auth, db } from 'src/config/firebase';
    import { User, Website } from 'src/types';
    
    const { user: authUser } = useAuth(auth);
    
    const userDocRef = doc(db, `users/${authUser.value?.uid}`);
    const user = useFirestore<User>(userDocRef);
    
    const websiteDocRef = computed(() =>
      doc(db, `websites/${user.value?.currentWebsiteId}`)
    );
    const website = useFirestore<Website>(websiteDocRef);
    </script>