Search code examples
flutterriverpodflutter-go-router

(go-router) Refresh riverpod state when going to a previous page


I am using using go_router 9.0.1 and go_router_builder 2.2.0 with riverpod 2.3.6. I have implemented go_router in my project and by default the package maintain the state of the previous page when using going to a sub-route. In my case I want that each time i go to a page, this same page reload/rebuild itself.

For example I have 2 routes :

  • page1 with subroutes like page1/sub1Page1 or - page1/sub2Page1
  • page2 with subroutes like page2/sub1Page1 or - page2/sub2Page1

If I go from page1 to page1/sub1Page1 using the Page1().go(context) method since I am using the type safe methods. I want to go back from page1/sub1Page1 to the page1 with the Page1().go(context) the state of the my riverpod provider is the same. It store the Page1 widget state somewhere meaning that I need to manually reset my providers manually using ref.invalidate(myProvider) before pushing another page. Does a solution exist to have this behavior ?

My current simplify implementation of go_router:

GoRouter(
      routes: $appRoutes,
      initialLocation: initialLocation,
      debugLogDiagnostics: true,
    );
@TypedShellRoute<HomeRoute>(
  routes: <TypedRoute<GoRouteData>>[
   TypedGoRoute<Page1Route>(
      path: Page1Route.path,
      name: Page1Route.name,
      routes: <TypedGoRoute<GoRouteData>>[
         TypedGoRoute<Sub1Page1>(
                  path: Sub1Page1.path,
                  name: Sub1Page1.name,
                ),
         TypedGoRoute<Sub2Page1>(
                  path: Sub2Page1.path,
                  name: Sub2Page1.name,
                ),
      ]
      TypedGoRoute<Page2>(
                  path: Page2.path,
                  name: Page2.name,
                ),
]);
class HomeRoute extends ShellRouteData {
  const HomeRoute();

  @override
  Widget builder(BuildContext context, GoRouterState state, Widget navigator) =>
      Layout(child: navigator);
}

class Page1 extends GoRouteData {
  const ProjectsRoute();

  static const String name = kNamePage1;
  static const String path = kPathPage1 ;

  @override
  Widget build(BuildContext context, GoRouterState state) => Page1Screen();
}

// Note that all the page or subpage are declared exactly as above.

Solution

  • It is possible by not maintain the state of a page but with the go_router package the feature is hidden.

    In the MaterialApp widget an parameter maintainState is available. But since we are using MaterialApp.router this parameter is no longer available.

    Is will appear again with the package only when we are trying to make a custom transition. We can find this example in the documentation:

    class FancyRoute extends GoRouteData {
      @override
      MaterialPage<void> buildPage(BuildContext context, GoRouterState state) =>
        CustomTransitionPage<void>(
          key: state.pageKey,
          child: FancyPage(),
          transitionsBuilder: (context, animation, animation2, child) =>
              RotationTransition(turns: animation, child: child),
        ),
    }
    

    The CustomTransitionPage is based on the MaterialPage widget where here again the maintainState property is available and where you need to set to false since by default it's to true. If you are in my case and don't want any animation between page, do not use the NoTransitionPage<T> class since this parameter is not available.

    I have created then based on their implementation of the no transition page a custom one below where the maintain state is false. You can then use it as documented in the go router package.

    /// Custom transition page with no transition.
    class CustomNoTransitionPage<T> extends CustomTransitionPage<T> {
      /// Constructor for a page with no transition functionality.
      const CustomNoTransitionPage({
        required super.child,
        super.name,
        super.arguments,
        super.restorationId,
        super.key,
      }) : super(
              transitionsBuilder: _transitionsBuilder,
              transitionDuration: Duration.zero,
              reverseTransitionDuration: Duration.zero,
              maintainState: false,
            );
    
      static Widget _transitionsBuilder(
        BuildContext context,
        Animation<double> animation,
        Animation<double> secondaryAnimation,
        Widget child,
      ) =>
          child;
    }