IjzerenHein / firestorter

Use Google Firestore in React with zero effort, using MobX 🤘
http://firestorter.com
MIT License
378 stars 50 forks source link

Document hasData returns false on existing document #69

Closed 0x80 closed 5 years ago

0x80 commented 5 years ago

In the code below this.user and this.settings are Firestorter documents. The last line prints Exists? true false when the settings exist. I would expect hasData to return true. Am I not understanding it properly?

      if (!isLoggedIn) {
        this.user.path = undefined;
        this.settings.path = undefined;
      } else {
        const currentUserId = getCurrentUserId();
        this.user.path = `users/${currentUserId}`;
        this.settings.path = `userSettings/${currentUserId}`;

        await this.settings.ready();

        /**
         * Temporary workaround, because hasData doesn't seem to behave
         */
        const doc = await db.doc(`userSettings/${getCurrentUserId()}`).get();
        console.log("Exists?", doc.exists, this.settings.hasData);
damonmaria commented 5 years ago

I'm guessing you're using Documents directly, rather than through a Collection? In that case what mode are they in? The default mode is auto which means they will only load data if an observer is watching them, and if no one is watching then ready() will resolve (although I'm not sure that's the best idea as that can lead to confusion as now, @IjzerenHein?).

If I've guessed correctly then you will also see that this.settings.snapshot is undefined. Set the mode (in the Document constructor options) to on and await fetch() rather than ready().

damonmaria commented 5 years ago

@0x80 Did my comment above match what's happening in your situation?

IjzerenHein commented 5 years ago

@0x80 Are you accessing the settings data anywhere from a reactive function? ready in itsself will not cause a fetch, but will merely make it possible for you to wait for data to arrive, before continuing with your async function.

I've ran into similar scenarios myself where I needed to access data, but that that data wasn't observed anywhere. In that use, I used the following code construct to make sure I could execute my async function:

if (!document.isActive && !document.hasData) {
  await document.fetch();
} else {
  await document.ready();
}
0x80 commented 5 years ago

@damonmaria @IjzerenHein Thanks, that must be it! I forgot about this issue because I'm not working on the code myself anymore.

My mistake was to think that setting the path would cause the data to be fetched. The settings document is not being watched by the time that path is set, so clearly nothing will happen then.

Adding a fetch before awaiting ready will surely fix the problem 👍