The property 'docs' cannot be unconditionally accessed because received can be 'null' Flutter
Asked Answered
E

4

14

After migrate to null-safety showing this error. What should I do now?

  Widget chatMessages() {
    return StreamBuilder(
        stream: messageStream,
        builder: (context, snapshot) {
          return snapshot.hasData
              ? ListView.builder(
                  padding: EdgeInsets.only(bottom: 70, top: 16),
                  itemCount: snapshot.data.docs.length,
                  reverse: true,
                  itemBuilder: (context, index) {
                    DocumentSnapshot ds = snapshot.data.docs[index];
                    return chatMessageTitle(
                        ds["message"], myUserName == ds["sendBy"]);
                  })
              : Center(child: CircularProgressIndicator());
        });
  }

After adding null check (!) showing this error <the getter 'docs' is not defined for the type of object>

              itemCount: snapshot.data!.docs.length,
              reverse: true,
              itemBuilder: (context, index) {
                DocumentSnapshot ds = snapshot.data!.docs[index];
Eligible answered 17/3, 2021 at 9:25 Comment(1)
Hi! what type is the snapshot.data? can you provide itThaumatology
L
21

You have to cast snapshot.data to its type. Suppose the type is QuerySnapshot (change this with the actual type of snapshot.data).

(snapshot.data! as QuerySnapshot).docs.length

Instead of typecasting at all locations, we can specify the type of stream in the StreamBuilder.

StreamBuilder<QuerySnapshot>(
  ...
);

Now snapshot.data is inferred as QuerySnapshot and no typecast is required.

snapshot.data!.docs.length
Lesh answered 17/3, 2021 at 9:56 Comment(0)
B
8

I have solved mine by adding StreamBuilder and builder(context, AsyncSnapshot snapshot).

 Widget chatMessages() {
     return StreamBuilder<QuerySnapshot>(
        stream: messageStream,
        builder: (context, AsyncSnapshot snapshot) {
       return snapshot.hasData
          ? ListView.builder(
              padding: EdgeInsets.only(bottom: 70, top: 16),
              itemCount: snapshot.data.docs.length,
              reverse: true,
              itemBuilder: (context, index) {
                DocumentSnapshot ds = snapshot.data.docs[index];
                return chatMessageTitle(
                    ds["message"], myUserName == ds["sendBy"]);
              })
          : Center(child: CircularProgressIndicator());
    });
 }
Butcher answered 7/6, 2021 at 8:7 Comment(0)
M
7

There are a few solutions:

  • Provide a type to your StreamBuilder:

    StreamBuilder<QuerySnapshot> (...)
    
  • Provide a type to the second parameter of your builder:

    builder: (context, QuerySnapshot snapshot)
    
  • Use as to downcast:

    (snapshot.data! as QuerySnapshot).docs['key']
    
Minna answered 23/5, 2021 at 9:25 Comment(0)
R
1

Add error and connection state checks like this:

      Widget chatMessages() {
        return StreamBuilder(
            stream: messageStream,
            builder: (context, snapshot) {
              if (snapshot.hasError) {
                return Text('Something went wrong');
                }
              if (snapshot.connectionState == ConnectionState.waiting) {
                return Text("Loading");
                }
              return ListView.builder(
                  padding: EdgeInsets.only(bottom: 70, top: 16),
                  itemCount: snapshot.data.docs.length,
                  reverse: true,
                  itemBuilder: (context, index) {
                    DocumentSnapshot ds = snapshot.data.docs[index];
                    return chatMessageTitle(
                    ds["message"], myUserName == ds["sendBy"]);
                    });
              });
        }
Ricci answered 17/3, 2021 at 9:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.