xcsob
xcsob

Reputation: 925

Flutter web Firebase onAuthStateChanges gets triggered every time I refresh the app

I'm developing a web app using flutter web.

Everytime I refresh a page, the onAuthStateChanges gets triggered and execute the functions that should be triggered only when a change in the auth state happens.

Is this behaviour intended?

To subscribe to the onAuthStateChanges, I wrapped my main widget with a stateful widget and listened to the onAuthStateChanges, as suggested here: Flutter Stream Builder Triggered when Navigator Pop or Push is Called

The following is my code:

my wrapper:

/// Wrapper for stateful functionality to provide onInit calls in stateles widget
class StatefulWrapper extends StatefulWidget {
  final Function onInit;
  final Widget child;
  const StatefulWrapper({@required this.onInit, @required this.child});
  @override
  _StatefulWrapperState createState() => _StatefulWrapperState();
}

class _StatefulWrapperState extends State<StatefulWrapper> {
  @override
  void initState() {
    if (widget.onInit != null) {
      widget.onInit();
    }
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return widget.child;
  }
}

my widget in main.dart:

Widget build(BuildContext context) {
    var router = MyRouter.Router();
    var authenticationService = locator<AuthenticationService>();
    var sharedPreferences = locator<SharedPreferencesService>();

    return StatefulWrapper(
      onInit: () {
        authenticationService.listenToAuthChanges();
      },
      child: FutureBuilder(
          future: sharedPreferences.getSharedPreferences('ruolo'),
          builder: (context, snapshot) {
            return MaterialApp(
              builder: ExtendedNavigator<MyRouter.Router>(
                initialRoute: MyRouter.Routes.startupView,
                guards: [AuthGuard(), AdminGuard()],
                router: router,
                navigatorKey: locator<NavigationService>().navigatorKey,
              ),
              title: 'Flutter Demo',
              theme: ThemeData(
                primarySwatch: Colors.blue,
                visualDensity: VisualDensity.adaptivePlatformDensity,
              ),
              onGenerateRoute: router.onGenerateRoute,
            );
          }),
    );
  }

Here is the method from the authenticationService:

  void listenToAuthChanges() {
    FirebaseAuth.instance.authStateChanges().listen((firebaseUser) async {
      if (firebaseUser == null) {
        navigationService.navigateTo(Routes.login);
      } else {
         navigationService.replaceWith(Routes.home);
      }
    });
  }

What happens is that when I refresh my page in the browser, the listener of this function gets triggered, and it navigate to the login if I'm not logged, on the home otherwise.

Is this intended? For me a listener should fire only when there is a change in what it listens to.

Upvotes: 0

Views: 619

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 599091

When the app loads, Firebase checks the authentication status of the user. At the start of that process is calls any active auth state listener with a null value. If the user can be authenticated, it then calls the listener with the user profile object.

So what you're seeing is indeed working as intended.

Upvotes: 3

Related Questions