Go Router (Flutter)- push the exact same route and refresh that route
Asked Answered
D

6

19

With GoRouter, Is there a way to push the exact same route with a different parameter and make the page reload? I am thinking of something like Navigator.pushReplacement

I am using context.go('/my_page/?param={someID}') to push to MyPage (a stateful widget)

The initial push to this route works fine and I load up the page for the particular ID

I am trying to push this same route again (replace the route and reload with different ID) using context.go('/my_page/?param={differentID}'). My breakpoints are hitting the return statement in my GoRoute pageBuilder, and I also hit a breakpoint in MyPage.build. I see the new ID passed into this widget when breakpointing in the build.

But the Page does not rebuild visually (or break in initState - side note, init state is used to load up a couple cubits with the passed in ID - could the page being a stateful widget be the problem?)

Maintain state on the Material Page is false. Also, pushing different routes works just fine.

Is this a stateful widget issue (meaning relocate all of my cubit init calls)? or is there a different way to push the same route?

EDIT _____________

This question was specific to rebuilding the same route, but the greater problem I was working on was to infinitely drill into the same page over and over again, while maintaining the navigation stack.

I was using a state manager to hold a list of routes and trigger the navigation by using context.go() to replace the current route completely.

is there a way to dynamically nest routes with context.push() while maintaining the entire nav stack?

Darlinedarling answered 22/8, 2022 at 17:30 Comment(5)
For clarification: Why is context.push() not fitting in your case? With .go you will replace the whole navigation stack so you can't "add" another route with itNelsen
Honestly I probably did a whole unnecessary workaround. Please see my Edit above to explain the entire issue I was trying to solveDarlinedarling
Your edit was very helpful, thanks. But I am really suprised about your obversations. When MyPage.build() is called, then this will lead to a visual update. Are you sure that ths is the problem? Do you want to show the code where you call context.go and the contents of MyPage.build?Nelsen
@PeterIrving: were you able to find a solution please ? I’m facing the same issue and both the answers below doesn’t seem to work. Any help would be much appreciated.Honest
Did someone find a solution about this problem ? @PeterIrvingExpanded
C
19

After some research, I have noticed that you can redirect to the same page by using pageKey: UniqueKey() in the definition of the GoRoute().

Example code from my project:

GoRoute(
    path: RoutePaths.serviceDetail.value,
    name: RouteNames.serviceDetail.value,
    pageBuilder: (context, state) {
        return CustomTransitionPage<void>(
            key: UniqueKey(),
            child: const ServiceDetailPage(),
            transitionsBuilder: (context, animation, secondaryAnimation, child) =>
            PageTransitions.subpageTransition(animation, child),
        );
    },
),
Chapiter answered 23/8, 2022 at 12:12 Comment(4)
This does push the same route again but just without any transition. So I don't think it's a solution. I am using go_router: ^3.1.1.Dichotomy
Maybe you should update the library to the latest version... 5.2.0 :DChapiter
Updated to 5.2.0 and it has the same behavior. It's just pushing the same route again but without any transition. You can verify it by pressing back after you try to push and then see if the same screen opens up or not.Dichotomy
Doesn't refresh the route 6.5Frogfish
B
3

None of the solutions worked for me. I had a similar problem, I'm making a quiz app and wanted to have one code(bloc and view) for all the questionnaires. I have a QuizPage:

class QuizPage extends StatelessWidget {
 const QuizPage({super.key, required this.id});
 final String id;
 @override
 Widget build(BuildContext context) {
  return BlocProvider(
   create: (context) => QuizBloc(id: id)..add(GetQuizEvent(id: id)),
   child: const QuizView(),
  );
 }
}

I use the id to change the questionnaire. On my start game I used

context.go('/game/1.1');

But on the end of the 1.1 questionnaire the go('/game/1.2') didnt refreshed the page so the bloc didnt made a request for the new questionnaire. My solution was to use the UniqueKey() suggested by @Pablo Insua and passed a unique key to the QuizPage on the router like this:

GoRoute(
    path: '/game/:id',
    builder: (context, GoRouterState state) =>
        QuizPage(
            key: UniqueKey(),
            id: state.pathParameters['id'] ?? "",
        ),
  ),

I`m on go_router version ^14.0.2

Burnejones answered 6/5 at 1:51 Comment(2)
What is the difference from Pablo's answer?Showdown
Now that you've pointed out the similarity between the answers, I've seen that in fact the only difference is that he used pageBuilder and I used builder. As others have commented, his answer didn't solve my problem, what it did was prevent my page from reloading, i.e. when I left context.go('/game/1.1'); and went to context.go('/game/1.2'); the page just didn't reload. Now I searched the difference between the two and found this.Burnejones
D
2

I think context.replace would accomplish what you are trying to do, since it should replace what is currently on the stack.

Dactylology answered 15/9, 2022 at 6:11 Comment(3)
What you want to say is to use GoRouter.of(getContext!).replace('page-route')Tarsometatarsus
Worked for me. Nice!Resiniferous
@ShehzadAhmad context.replace() is an extension method which uses GoRouter.of(context).replace()Gemina
A
2

I used the following method, reading the docs strings for context.go method helped a lot

context.pushReplacement(url);
Abbotson answered 1/5 at 21:18 Comment(0)
S
0

So this problem will only show up if the route is nested (shell routes) and you have pushed a new route using context.pushNamed('route-name') or context.push('name').

You can simply await the child route to pop using the following code snippet.

onTap: () async {
  final bool? result = await context.push<bool>('/page2');
  if(result ?? false)...
  // TODO: here can be the refresh logic
}

This is mentioned in go_router docs. This won't reinitiate the page. . If you want to reinitiate the page every time the page shows up. The answer will be using UniqueKey() as suggested above. But this will cause issue with transition animation.

Sassan answered 27/7, 2023 at 21:53 Comment(1)
Could you point where it's mentioned in the docs?Watchful
T
0

Another way to do that is by passing in extra param current timestamp. This way you can avoid the caching of the page

context.go(yourUrlHere, extra: DateTime.now().millisecondsSinceEpoch)
Toccaratoccata answered 12/8 at 16:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.