Panda Power
Panda Power

Reputation: 335

Document Stream snapshot.hasData returns true but no data, how to fix this?

I am streaming a Document snapshot from Firestore, but snapshot.hasData returns true when there is nothing in the db. This causes my code to fail when try retrieve value out of the snapshot.

How do I fix this?

I tried print out snapshot.Data just got an Documentsnapshot instance. Also thought about provide initial data to the stream, but I do not know how to provide an empty DocumentSnapshot data type.

If I manually insert a record in to firestore, it works fine.

StreamBuilder<DocumentSnapshot>(

          stream: Firestore.instance.collection('UserDetails').document(widget.uid).snapshots(),
          builder: (context, snapshot){

            if(snapshot.hasError){
              widget._err = snapshot.error;
            } else if (snapshot.connectionState == ConnectionState.waiting){
              widget._loadingUserInfo = true;
            } else if (snapshot.hasData){
              nameController.text = snapshot.data['name'];
              ageController.text = snapshot.data['age'];
              introController.text = snapshot.data['intro'];
              widget._loadingUserInfo = false;
            }
)

I am trying to get user value from Firestore to populate their form if there is a value or user exists.

Now it just fails.

Upvotes: 1

Views: 5289

Answers (6)

Ray Li
Ray Li

Reputation: 7919

The cause of the confusion is that Firestore returns a DocumentSnapshot even when there is nothing in the database to return.

FutureBuilder<DocumentSnapshot>(
    future: firestore
        .document('collection/non_existant_document')
        .get(),
    builder: (BuildContext context,
        AsyncSnapshot<DocumentSnapshot> snapshot) {
      if (snapshot.hasData) {
        print('Has Data');
      }
    }),

The above code returns an empty DocumentSnapshot. However, since it returns DocumentSnapshot in data, hasData evaluates to true.

To check if the DocumentSnapshot contains data, use

if (snapshot.data?.exists ?? false) {}

Upvotes: 2

Ahmed Hafiz
Ahmed Hafiz

Reputation: 67

May be you can try checking if data is null with:
if (snapshot.data == '[]') then

In your case...

....
else if (snapshot.hasData && snapshot.data.toString() != '[]') then){
   nameController.text = snapshot.data['name'];
   ageController.text = snapshot.data['age'];
   introController.text = snapshot.data['intro'];
   widget._loadingUserInfo = false;
}

Took me an hour to figure this out...

Upvotes: 0

Nimish Peter Pandey
Nimish Peter Pandey

Reputation: 61

I've found that although print( snapshot.hasData ); gets true, print( snapshot.data.documents.isEmpty ); and print( snapshot.data.exists ); get true as well..

hence, to solve my issue, I used:

if (!snapshot.hasData || snapshot.data.documents.isEmpty) //for QuerySnapshot

OR

if (!snapshot.hasData || !snapshot.data.exists) //for DocumentSnapshot

Upvotes: 6

oodavid
oodavid

Reputation: 2326

snapshot.hasData will return true for an empty dataset, ie:

snapshot.data = []

Personally, I consider hasData to mean "has a response".

Upvotes: 2

Sebastian
Sebastian

Reputation: 3894

Why don't you just add a validation?

Something like

if (snapshot.hasData && (snapshot.data == null) return SizedBox();

Also if you are retrieving a list you could check if data != null and snapshot.data.length == 0;

Upvotes: 0

R&#233;mi Rousselet
R&#233;mi Rousselet

Reputation: 277057

It is impossible for hasData to return true when there no data.

hasData is nothing but a shorthand for:

snapshot.data != null

Which means that you do have data. But maybe not the data you want.

Upvotes: 0

Related Questions