0

I have a users Firestore collection where the ids are my users uid. When a user logs in (with Firebase auth), i'd like to wrap the whole application by the corresponding firestore document.

My code is the following:

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        StreamProvider(
          create: (context) => FirebaseFirestore.instance
              .collection('users')
              .doc(FirebaseAuth.instance.currentUser?.uid)
              .snapshots(),
          initialData: null,
        )
      ],
      child: MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
          useMaterial3: true,
        ),
        home: const AuthentificationWapper(),
      ),
    );
  }
}

class AuthentificationWapper extends StatefulWidget {
  const AuthentificationWapper({super.key});

  @override
  State<AuthentificationWapper> createState() => _AuthentificationWapperState();
}

class _AuthentificationWapperState extends State<AuthentificationWapper> {
  @override
  Widget build(BuildContext context) {
    var userList =
        Provider.of<DocumentSnapshot<Map<String, dynamic>>?>(context);

    var isLogged = userList?.data() != null;

    return Scaffold(
        appBar: AppBar(
          backgroundColor: Theme.of(context).colorScheme.inversePrimary,
          title: Text('test'),
        ),
        body: Center(
          child: isLogged ? Text('YOU ARE LOGGED') : LogginAccount(),
        ));
  }
}

The problem is when the user logs in, AuthentificationWapper is not being updated (the log in form is still being displayed). I need to make a hot reload in order to see the text YOU ARE LOGGED

2
  • Check out Check current auth state section of the documentation on how to listen to the changes in authentication state. Commented Feb 8 at 19:26
  • Currently your code uses the FirebaseAuth.instance.currentUser value at the time when MyApp is built that's why it works on hot reload. But it is not updated when the user is logged in or out. Commented Feb 8 at 19:31

2 Answers 2

2

As Peter commented, right now your code uses FirebaseAuth.instance.currentUser to determine the current user, which happens to be null when that code happens to run.

What you'll want to do instead is listen for the current user by listening for authStateChanges as shown in the documentation on getting the current user. The FirebaseAuth.instance.authStateChanges() in the sample code there gives you a Stream, so you can use another StreamBuilder or StreamProvider to also make the app respond to auth state changes.

Sign up to request clarification or add additional context in comments.

2 Comments

I see, thank you, but i also want my firestore document to be a provider (i want to have access to this document everywhere in my app), how can i do so? do i need a provider inside a provider ? (the first provider would be the one listening to FirebaseAuth.instance.authStateChanges() and the second one would be the one listening to the firestore document ?
I assume you'd need two separate providers: one for the user and one for the documents. I am no expert on providers, but a quick search shows some promising results: google.com/…
0

Multiprovider widget did the trick

return MultiProvider(
      providers: [
        Provider<AuthentificationService>(
          create: (_) => AuthentificationService(FirebaseAuth.instance),
        ),
        StreamProvider<User?>(
          create: (context) =>
              context.read<AuthentificationService>().authStateChanges,
          initialData: null,
        ),
        StreamProvider<DocumentSnapshot?>(
          create: (context) {
            final authService = context.read<AuthentificationService>();
            return authService.authStateChanges.asyncMap((user) {
              if (user != null) {
                print('Creating Firestore stream for user: ${user.uid}');
                return FirebaseFirestore.instance
                    .collection('users')
                    .doc(user.uid)
                    .get();
              }
              print('No user logged in, returning null');
              return null;
            });
          },
          initialData: null,
        ),
      ],
      child: MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
          useMaterial3: true,
        ),
        home: const AuthentificationWapper(),
      ),
    );

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.