How to clear go_router navigation history in redirect method
Asked Answered
R

4

8

On application start i have a few configuration pages (that can be skipped by user) that user setup once, and finally ends up in dashboard page.

Possible navigation flows (depend on what user already setup, and what skipped in the past):

'/' -> '/dashboard'
'/' -> '/language' -> '/dashboard'
'/' -> '/welcome'/ -> '/dashboard'
'/' -> '/welcome'/ -> '/language' -> '/dashboard'

If i go from /welcome to /language I use context.push('/language') to be able to navigate back - but i am aware that it can be redirected to /dashboard. so if i go from anywhere to /dashboard, i always want to end up with clear navigation history, so that if user click backButton on dashboard, the application should shut down and there is no back arrow in dashboard AppBar.

final router = GoRouter(
  routes: <GoRoute>[
    GoRoute(
      path: '/',
      redirect: (_, __) => '/welcome',
    ),
    GoRoute(
      path: '/welcome',
      builder: (_, __) => const WelcomePage(),
      redirect: (_, __) async {
        final skip = await ...
        if (skip) {
          return '/language';
        }

        return null;
      },
    ),
    GoRoute(
      path: '/language',
      builder: (_, __) => const LanguagePage(),
      redirect: (_, __) async {
        final skip = await ...
        if (skip) {
            /*
            * TODO MAKE SOME MAGIC HERE TO CLEAR HISTORY
            */
            return '/dashboard';
        }

        return null;
      },
    ),
    GoRoute(
      path: '/dashboard',
      builder: (_, __) => const DashboardPage(),
    ),
  ],
);
Repose answered 14/10, 2022 at 6:34 Comment(4)
I'm having the same problem. Hopefully, someone has an answer to it...Stichometry
The only way I see is to redirect to a route that was previously on the stack. This will cause the stack to reset to that position in the queue.Production
Created an issue on github for this github.com/flutter/flutter/issues/116164Production
did you found the answer @Michał Dziwota i am also facing the same issueBusinesslike
M
8

I'll repost this answer here as well.

This is what seems to have worked for me. I admit it's kind of a hack.

  1. Have a global GoRouter instance
GoRouter? globalGoRouter;

GoRouter getGoRouter() {
  return globalGoRouter ??= getRoutes();
}

GoRouter getRoutes() {
return GoRouter(
    initialLocation: '/',
    routes: <RouteBase>[
      GoRoute(
        path: '/',
        builder: (BuildContext context, GoRouterState state) {
          return const HomePage();
        },
        routes: <RouteBase>[
          GoRoute(
            name: 'auth',
            path: 'auth',
            builder: (BuildContext context, GoRouterState state) {
              return const AuthScreen();
            },
          ),
          GoRoute(
            name: 'login',
            path: 'login',
            builder: (BuildContext context, GoRouterState state) {
              return const LoginScreen();
            },
          ),
          GoRoute(
            name: 'landing',
            path: 'landing',
            builder: (BuildContext context, GoRouterState state) {
              return const LandingScreen();
            },
          ),
        ),
      ],
   );
}
  1. Create this function
void clearAndNavigate(String path) {
  while (getGoRouter().canPop() == true) {
    getGoRouter().pop();
  }
  getGoRouter().pushReplacement(path);
}
  1. Then you call the function
clearAndNavigate('login');

Open to suggestions for a less 'hacky' way

Magnetize answered 21/8, 2023 at 17:45 Comment(0)
S
6

Here's an extension on this answer

extension GoRouterExtension on GoRouter{
  void clearStackAndNavigate(String location){
    while(canPop()){
      pop();
    }
    pushReplacement(location);
  }
}

usage: GoRouter.of(context).clearStackAndNavigate('login')

Staffman answered 7/4 at 9:28 Comment(0)
H
3

Love the answer by @Alfiepoleon on top. I implemented it and it works great for me. The only change I made was to not to pass the GoRouterState but instead access the functions I need through context.

void clearAndNavigate(String path) {
  while (context.canPop() == true) {
    context.pop();
  }
  context.pushReplacement(path);
}
Humanitarianism answered 10/10, 2023 at 16:44 Comment(0)
O
2

A more straightforward way to do this, which is an abstraction of this other answer, would be:

void clearStackAndNavigate(BuildContext context, String path) {
  while (GoRouter.of(context).canPop()) {
    GoRouter.of(context).pop();
  }

  GoRouter.of(context).pushReplacement(path);
}
Osmo answered 2/10, 2023 at 13:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.