1

I'm getting an error in a FutureBuilder while trying to retrieve data from the Firestore database.  The error message is:

The following StateError was thrown building FutureBuilder<DocumentSnapshot<Object?>>(dirty, state: _FutureBuilderState<DocumentSnapshot<Object?>>#9feea): Bad state: field does not exist within the DocumentSnapshotPlatform

The relevant error-causing widget was:   FutureBuilder<DocumentSnapshot<Object?>> FutureBuilder:file:///Users/cy/AndroidStudioProjects/improve_practice_app/lib/app/community/tabs/profile_tab.dart:47:24

I reviewed different SO threads and and still have no idea what to do to fix my code.  Firebase is definitely working properly and I don't see any missing fields.  Any help will be appreciated.  Thanks.

class ProfileTab extends StatefulWidget {
  const ProfileTab({
    Key? key,
  }) : super(key: key);

  @override
  State<ProfileTab> createState() => _ProfileTabState();
}

class _ProfileTabState extends State<ProfileTab> {
  final currentUser = Auth().currentUser?.uid;

  @override
  Widget build(BuildContext context) {
    return SafeArea(
        child: CustomScrollView(slivers: <Widget>[
      SliverToBoxAdapter(
          child: FutureBuilder<DocumentSnapshot<Map<String, dynamic>>>(
              future: Auth().usersReference.doc(currentUser).get(),
              builder: (context, snapshot) {
                if (snapshot.connectionState == ConnectionState.waiting) {
                  return const AdaptiveCircularProgress();
                }
                AppUser appUser = AppUser.fromDocument(snapshot.data);
                return UserProfileHeaderContainer(headerContent: []);
              }))
    ]));
  }
}

class AppUser {
  AppUser({
    this.bio,
    this.displayName,
    this.followers,
    this.following,
    this.photoUrl,
    this.userID,
    this.userCart,
    this.userName,
  });

  final String? bio;
  final String? displayName;
  final List? followers;
  final List? following;
  final String? photoUrl;
  final List? userCart;
  final String? userID;
  final String? userName;

  factory AppUser.fromDocument(DocumentSnapshot? doc) {
    return AppUser(
      bio: doc?[FirebaseString.bio],
      displayName: doc?[FirebaseString.displayName],
      followers: doc?[FirebaseString.followers],
      following: doc?[FirebaseString.following],
      photoUrl: doc?[FirebaseString.photoUrl],
      userCart: doc?[FirebaseString.userCart],
      userID: doc?[FirebaseString.userID],
      userName: doc?[FirebaseString.userName],
    );
  }

  Map<String, dynamic> toJson() => {
    FirebaseString.bio: bio,
    FirebaseString.displayName: displayName,
    FirebaseString.followers: followers,
    FirebaseString.following: following,
    FirebaseString.photoUrl: photoUrl,
    FirebaseString.uid: userID,
    FirebaseString.userCart: userCart,
    FirebaseString.userName: userName,
  };
  
}
Carleton Y
  • 289
  • 5
  • 17

2 Answers2

3

You are parsing it wrong. You need to do something like.

factory AppUser.fromDocument(DocumentSnapshot<Map<String, dynamic>> doc) {

// it's the data map which has all the info
final map = doc.data()

return AppUser(
  bio: map[FirebaseString.bio],
  ....,
  ....,
  );
}
aman
  • 205
  • 2
  • 4
  • 1
    @aman I think your answer is correct. This is probably related to recent changes in DocumentSnapshot, your factory is looking for the data map, which used to be in doc, but nows its in doc.data(). Using "doc.data()" and then trying to get the value by accessing the key should solve the issue. – Priyashree Bhadra Feb 14 '22 at 12:26
  • @aman. Your answer was the solution. Thanks for the help. I needed it. – Carleton Y Feb 14 '22 at 15:19
0

Here is another solution: before calling AppUser.fromDocument(DocumentSnapshot? doc), you can check whether the doc does have data or not by calling: value.exists. if it returns true then call the AppUser.fromDocument(DocumentSnapshot doc), if false then you can handle the null case