Home > Blockchain >  Flutter Futurebuilder snapshot has no data
Flutter Futurebuilder snapshot has no data

Time:09-25

After the first Log In in my App I want to fetch the userdata with a Futurebuilder. Therefore I want to fetch the data from firestore and store the values in a static Helper class:

/// Helper Class
class UserManager {
  static Map<String, dynamic> userdata = null;
}

class FireBaseHandler {

  final CollectionReference usersCol = FirebaseFirestore.instance.collection(
      'users');
  final myUser = FirebaseAuth.instance.currentUser;

  /// fetch UserData
  Future getUserData() async {
    try {
      await usersCol
          .doc(myUser.uid)
          .get().then((value) => UserManager.userdata = value.data());
      return UserManager.userdata;
    } catch (e) {
      print(e.toString());
    }
  }
}

      /// Futurebuilder in main Code

      FireBaseHandler handler = FireBaseHandler();
      return FutureBuilder(
                      future: handler.getUserData(), /// get userData and store it in Helper class
                      builder: (context, userDataSnapshot) {
                        if (userDataSnapshot.hasData) {
                          print(UserManager.userdata);
                          return HomeScreen();
                        } else {
                          return Scaffold(
                            body: Center(
                              child: CircularProgressIndicator(),
                            ),
                          );
                        }
                      });

The Problem is that the snapshot from the Futurebuilder never has Data so userDataSnapshot.hasData is never true and it stays in loading Screen. Only when I hot reload the snapshot has Data and I go to the homescreen. Whats the Problem?

CodePudding user response:

Don't mix async / await and .then, they both do the same but the two syntaxes can't be mixed. Also set the appropriate data type for your Future function and return the result of database fetch. You don't really need try/catch, you will handle errors in the FutureBuilder:

Future<Map<String, dynamic>> getUserData() async {
    return await usersCol.doc(myUser.uid).get();
}
return FutureBuilder(
  future: handler.getUserData(), /// get userData and store it in Helper class
  builder: (context, userDataSnapshot) {
    if (userDataSnapshot.hasError) {
        return const Text('Error');
    }
    if (userDataSnapshot.hasData) {
      if (!snapshot.data!.exists) {
        return const Text('Document not found');
      }
      else {
        UserManager.userdata = userDataSnapshot.data!.data();
        print(UserManager.userdata);
        return HomeScreen();
      }
    }
    // still loading
    else {
      return Scaffold(
        body: Center(
          child: CircularProgressIndicator(),
        ),
      );
    }
  });

CodePudding user response:

I think the problem is the way you initialize UserManager.userdata in a lambda function inside the then (() {...}) this initialization is local to this function, reason why UserManager.userdata remains null try to do as in the example below :

  Future getUserData() async {
     UserManager.userdata = (await usersCol.doc(myUser.uid).get()).data();
     return UserManager.userdata;
    
  }

I think the value of UserManager.userdata will be available only in getUserData()
if you want to use UserManager.userdata in another class, I guess it will be null,

Good way below, your function got just to return

  Future<Map<String, dynamic>> getUserData() async {
    return  (await usersCol.doc(myUser.uid).get()).data();
  }
  • Related