Why document doesn't exist. But all time !snapshot.hasData is false

Issue

I make sign up system and managing user information.

When sign-up, users are required to write user name, and it’s stored in firestore.

User data are stored like this;

Img

And trying to get userName with the code;

CollectionReference users = FirebaseFirestore.instance.collection('users');

return FutureBuilder<DocumentSnapshot>(
  future: users.doc(FirebaseAuth.instance.currentUser!.uid).get(),
  builder:
      (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
    if (snapshot.hasError) {
      return Text("Something went wrong");
    }

    print("${!snapshot.hasData} ${!snapshot.data!.exists}"); // always "false true"
    if (!snapshot.hasData && !snapshot.data!.exists) {
      return Text("Document does not exist");
    }

    if (snapshot.connectionState == ConnectionState.done) {
      Map<String, dynamic> data =
          snapshot.data!.data() as Map<String, dynamic>;
      return Text("User Name: ${data['userName']}");
    }

    return const CircularProgressIndicator();
  },
);

However always return Text("Document does not exist"); is called, and userName is not displayed.

Why doesn’t userName returned? I searched for a misspelling but couldn’t find it.
This issue has taken a lot of time today. Thank you.

Solution

The snapshot.data that you are referring to is the AsyncSnapshot that is used to monitor the status of the asynchronous operation. Its hasData becomes true when the asynchronous operation has completed: so when it is done reading the DocumentSnapshot from the database.

To detect whether the DocumentSnapshot actually exists, you need to check its exists property.

A quick summary of common statuses:

Object.property Value Explanation
AsyncSnapshot.hasData false the asynchronous operation has either not yet completed, or did not result in a DocumentSnapshot (for example: if there was a network error). Calling snapshot.data will result in an error message.
AsyncSnapshot.hasData true the asynchronous operation has completed and you can safely call snapshot.data on it to get the DocumentSnapshot.
DocumentSnapshot.exists false the document you requested does not exist, and calling document.data on the snapshot will result in an error.
DocumentSnapshot.exists true the document you requested exists, and you can access its data.

So your !snapshot.hasData will be false once the AsyncSnapshot is done loading the DocumentSnapshot. To determine whether the document actually exists, use snapshot.hasData && snapshot.data!.exists.

I also recommend checking out my explanation here of the various types of snapshots in Flutter code: What is the difference between existing types of snapshots in Firebase?

Answered By – Frank van Puffelen

Answer Checked By – Marie Seifert (FlutterFixes Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *