Milad-Akarie / auto_route_library

Flutter route generator
MIT License
1.59k stars 405 forks source link

AutoRouterDelegate.declarative is deprecated - use guards instead - no docs? #1928

Open realitymolder opened 6 months ago

realitymolder commented 6 months ago

Hey there, I've tried to use AutoRouterDelegate.declarative on AutoRoute 8, but it seems like it got deprecated. The deprecation message says that I should use guards instead. My goal here is to create an auth routing by AuthState, but I don't want the app to show me the routing animations between pages when the app will route the user after an auth check. How should I convert it into guards? I see no docs on the deprecation message or changelog. P.S due to the fact that I use AutoTabsScaffold I cannot return the HomePage because it has children (is a router of its own).

Code example of the init Widget of the app that should change into guards, apparently.

class HomePage extends HookConsumerWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    // Listen to user provider and return relevant screen
    return ref.watch(userControllerProvider).when(
      // Has user - Home screen
      data: (user) {
        // Loading the services in the background
        loadServices(ref, user);
        return userHomePage;
      },
      // Error while loading the user - error screen
      error: (e, s) {
        logger.e('Error Loading Profile $e', stackTrace: s);
        return const ErrorPage();
      },
      // Loading the user - circular loading
      loading: () {
        logger.i('Loading Profile ...');
        return const LoadingPage(shouldload: true);
      },
    );
  }
  }

  /// The home page
  Widget get userHomePage => AutoTabsScaffold(
        extendBody: true,
        backgroundColor: R.colors.white,
        routes: const [
          // MomentsRouter(),
          BrowseRouter(),
          ConnectionsRouter(),
        ],
        resizeToAvoidBottomInset: false,
        floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
        floatingActionButton: const HomeFloatingActionButton(),
        bottomNavigationBuilder: (context, tabsRouter) =>
            const HomeBottomNavigation(),
      );

Thank you, D.

realitymolder commented 6 months ago

@Milad-Akarie

Milad-Akarie commented 6 months ago

@realitymolder share your existing implementation using declarative. fyi it's only deprecated in root scope, you can still use declarative in sub-routers

realitymolder commented 6 months ago

@realitymolder share your existing implementation using declarative. fyi it's only deprecated in root scope, you can still use declarative in sub-routers

I used it in root, as a routerDelegate:

   routerDelegate: AutoRouterDelegate.declarative(
          _appRouter,
          routes: (_) {
            return auth.when(
              data: (authState) {
                return authState.when(
                  finished: () {
                    ref
                        .read(userControllerProvider.notifier)
                        .getAuthenticatedUser();
                    // if they are logged in and finished , bring them to the Home page:
                    return [const HomeRoute()];
                  },
                  onboarding: () {
                    // if they are logged in but didnt finish , bring them to the Onboarding page
                    return [const OnboardingRoute()];
                  },
                  unAuthenticated: () {
                    // if they are not logged in, bring them to the Login page
                    return [const LoginRoute()];
                  },
                );
              },
          error: (e, s) => [const ErrorRoute()],
          loading: () => [const LoadingRoute()],
        );
        },
        ),
        routeInformationParser:
            _appRouter.defaultRouteParser(includePrefixMatches: true),
mxknt commented 6 months ago

@Milad-Akarie Just want to tag along and say that I'm using AutoRouter the exact same way, with a declarative router at the root of my app to handle the auth state. Also curious what the alternative is if this pattern is being deprecated. Thanks for all your work on this awesome library!

Milad-Akarie commented 6 months ago

@realitymolder @mxknt you had no problems with deep-linking when working with the root declarative router?

realitymolder commented 6 months ago

@realitymolder @mxknt you had no problems with deep-linking when working with the root declarative router?

This is a new project, so didn't have a chance yet to get into deep linking. Also, my implementation of the router delegate (root) was very young, and I tried to go with the "best practice" to make sure I solve this issue in the best way possible. With that said, It is quite an issue due to the fact that it's not a boolean auth but a Tri auth situation and 2 of those are dependent on an async value that comes from the server...

Milad-Akarie commented 6 months ago

@realitymolder what you can do is have a sub-router dedicated to auth-flow and guard your home route with an auth guard

realitymolder commented 6 months ago

@realitymolder what you can do is have a sub-router dedicated to auth-flow and guard your home route with an auth guard

I'm trying to implement that now, but it seems like I'm not able to update the state of the guard, like the guard is not listening, although I'm using .watch (riverpod) Only on hot reload, the app will show the relevant event example:

class AuthGuard extends AutoRouteGuard {
  AuthGuard({required this.ref});
  final Ref ref;

  @override
  void onNavigation(NavigationResolver resolver, StackRouter router) {
    ref.read(authControllerProvider.notifier).loadAuthState();

    logger.d('message from AuthGuard');
    ref.watch(authControllerProvider).when(
          data: (authState) {
            authState.when(
              unAuthenticated: () {

                logger.d('unAuthenticated');
                // resolver.redirect(const LoginRoute());
                router.popAndPush(const LoginRoute());
              },
              onboarding: () {
                logger.d('onboarding');
                router.popAndPush(const OnboardingRoute());

                // resolver.next(false);
              },
              finished: () {
                logger.d('finished');
                resolver.next();
              },
            );
          },
          error: (error, stackTrace) =>
              logger.e(error.toString(), stackTrace: stackTrace),
          loading: () {
            logger.d('Loading AuthGuard...');
            // ref.read(authControllerProvider.notifier).loadAuthState();
          },
        );
  }
}
Tamerlanchiques commented 2 months ago

Please update docs

naveenr-egov commented 2 months ago

@Milad-Akarie any update on this?