Reputation: 81
I'm trying to create a simple navigation according to auth state to Firebase, but for some reason
Provider.of<FirebaseUser>(context)
always returns null as a first value in the widget build method. So my app always navigates to auth screen and after that gets the real user status from Firebase.
What am I missing here?
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
.then((_) => runApp(App()));
}
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StreamProvider<FirebaseUser>.value(
//value of user always corresponds to the right auth status
value: FirebaseAuth.instance.onAuthStateChanged.map((FirebaseUser user) {
AuthService.instance.user = user;
return user;
}),
child: MaterialApp(
title: 'Title',
theme: lightTheme,
home: LandingScreen(),
),
);
}
}
class LandingScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
//Even though the user is logged in it returns null for the first build() call
final user = Provider.of<FirebaseUser>(context);
return AnimatedSwitcher(
duration: const Duration(milliseconds: 3000),
transitionBuilder: ...,
child: user != null ? const MainScreen() : const AuthScreen(),
);
}
}
Upvotes: 6
Views: 3692
Reputation: 10453
You can subscribe to FirebaseAuth authStateChanges()
stream to listen to the user's current authentication state.
FirebaseAuth.instance
.authStateChanges()
.listen((User? user) {
if (user == null) {
print('User is currently signed out!');
} else {
print('User is signed in!');
}
}
);
But checking the code you've provided, auth state is being fetched on final user = Provider.of<FirebaseUser>(context);
. If the provider wasn't updated upon user login, then it will always be null. You may want to use FirebaseAuth.instance.currentUser()
instead.
Upvotes: 1