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
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 Answers
Reset to default 2As 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.
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(),
),
);
FirebaseAuth.instance.currentUser
value at the time whenMyApp
is built that's why it works on hot reload. But it is not updated when the user is logged in or out. – Peter Koltai Commented 2 days ago