1

I use Firebase Authentication and Cloud FireStore plugin. I want to use the best practice and it's very hard to find a good example of what i try to do. Every example on internet show using Auth only or using Firestore only.

But what if want to have a profile page of the currently logged user? I first need to retrieve the current userID so do i use a FutureBuilder ? and now i want to result from that user so do i use a StreamBuilder right after? It's really hard to understand best practice about flutter.

Some people say to do it in a statefullwidget, put a reference of the snapshot in the initstate Other people are using Statefull Widget.

Here is a code example of what i try to achieve but i do think it's the dumb way. PS: AuthHelper().uid() return the UID as a string. I created a function for this i don't know how to do it in 1 line with FireAuth.

class EducatorScreen extends StatelessWidget {
  static const routeName = '/educatorScreen';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: geAppBar(context, 'Contrôle Éducateur'),
      body: FutureBuilder(
          future: AuthHelper().uid(),
          builder: (BuildContext context, AsyncSnapshot<String> uidSnapshot) {
            if (uidSnapshot.connectionState == ConnectionState.waiting) {
              return CircularProgressIndicator();
            }
            return StreamBuilder(
                stream: Firestore.instance
                    .collection('users')
                    .document(uidSnapshot.toString())
                    .snapshots(),
                builder: (ctx, educatorSnapshot) {
                  if (educatorSnapshot.data['favoriteNursery'] != 'none') {
                    return nurseryWidget(
                        context, educatorSnapshot.data['favoriteNursery']);
                  } else {
                    return noNurseryWidget(context);
                  }
                });
          }),
    );
  }
}
class AuthHelper {
  Future<String> uid() async {
    // Return UserID
    final FirebaseUser user = await FirebaseAuth.instance.currentUser();
    return user.uid;
  }
}
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Jason Simard
  • 103
  • 5
  • 18

1 Answers1

2

Nesting builders like this is indeed normal.

Your FutureBuilder will be resolving until the user is authenticated. You might choose to show something like "authenticating user..." before that.

Your StreamBuilder will then be resolving until the data is loaded. You might show something like "loading user data..." while that is happening.

Also see my question and answers here, about loading data from two streams, in which one solution was to nest builders too: How do I join data from two Firestore collections in Flutter?

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Thanks Frank, appreciated. I think the way i get my userID is not optimal with FireAuth, what do you suggest? Is everyone create a async fonction to return a string? – Jason Simard Aug 27 '20 at 17:37
  • 1
    Ensuring that the user is authenticated is inherently an asynchronous operation, as it may require calls to the server, and can change at any time (as the token is refresh every hour). So what you're doing looks fine to me. It'll be a different syntax in the latest FlutterFire libraries, as they switched over to a state change listener: https://firebase.flutter.dev/docs/auth/usage#authentication-state – Frank van Puffelen Aug 27 '20 at 17:44