Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter Auto Route: How to set initial route programmatically?

Tags:

flutter

dart

I have a log-in screen with a home screen. Once a user logs in, it redirects the user to the home screen. However, I have a bloc which checks if user was authenticated before, if yes, it redirects the user straight to the home screen.

However, it doesn't work as intended. The "isLoggedIn" bool value changes, but the UI doesn't react. How to solve this?

Here's the code

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:harnasik/core/router/app_router.gr.dart';
import 'package:harnasik/core/style/custom_colors.dart';
import 'package:harnasik/features/authorization/presentation/blocs/log_in/log_in_bloc.dart';
import 'package:harnasik/generated/l10n.dart';
import 'package:harnasik/injection_container.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await InjectionContainer().init();
  runApp(const HarnasikApp());
}

class HarnasikApp extends StatefulWidget {
  const HarnasikApp({Key? key}) : super(key: key);

  @override
  _HarnasikAppState createState() => _HarnasikAppState();
}

class _HarnasikAppState extends State<HarnasikApp> {
  late final LogInBloc logInBloc;
  late bool isLoggedIn;
  final AppRouter _appRouter = sl();

  @override
  void initState() {
    logInBloc = sl();
    super.initState();
    isLoggedIn = false;
    logInBloc..add(CheckIfUserLoggedInEvent());
  }

  @override
  void dispose() {
    logInBloc.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return BlocListener(
      bloc: logInBloc,
      listener: (context, state) {
        if (state is LoggedInState) {
          isLoggedIn = true;
        } else if (state is LogInErrorState) {
          print('Error'); // For tests only
        }
      },
      child: MaterialApp.router(
        debugShowCheckedModeBanner: false,
        theme: ThemeData(
          primaryColor: CustomColors.blue,
          fontFamily: 'Lato',
        ),
        routerDelegate: _appRouter.delegate(
          initialRoutes: [
            if (!isLoggedIn) const LogInScreen() else const HomeScreen(),
          ],
        ),
        routeInformationParser: _appRouter.defaultRouteParser(),
        localizationsDelegates: const [
          S.delegate,
          GlobalWidgetsLocalizations.delegate,
          GlobalMaterialLocalizations.delegate,
          GlobalCupertinoLocalizations.delegate
        ],
        supportedLocales: S.delegate.supportedLocales,
      ),
    );
  }
}
like image 964
szakes1 Avatar asked Mar 03 '26 04:03

szakes1


1 Answers

I solved this same problem using an auto_route guard like this:

/// An auto_route guard object that routes the user to our landing page if
/// signed in and to the home page if not signed in 
class GetInitialRoute extends AutoRouteGuard {

  @override
  void onNavigation(NavigationResolver resolver, StackRouter router) {

    // Here we check if the user is logged in using FirebaseAuth (not currentUser --> 
    // not logged in)
    if (FirebaseAuth.instance.currentUser == null) {
      // if we do not have a user yet, we resume navigation to the sign in page 
      // with path: '/'
      resolver.next(true);
    } else {
      // if we already have a logged in user, we push them to our home page
      router.push(const HomeRoute());
    }
  }
}

Please read this article on authentication in auto_route LINK and this article on route_guards LINK to learn more. These articles also explain how to apply a guard to your routes.

like image 96
MRR Avatar answered Mar 04 '26 19:03

MRR