Lemonderon
Lemonderon

Reputation: 81

Flutter: StreamProvider<FirebaseUser> with onAuthStateChanged always returns null as a first value

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

Answers (1)

Omatt
Omatt

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

Related Questions