Flutter GoRouter push/go/pushNamed do not work

633 Views Asked by At

I want a page to be pushed when I click a button and I am using GoRouter package from Flutter. However, I tried various ways of pushing, nothing works. I tried with Navigator instead of GoRouter, and it did work, however I want to do deep-linking so the Navigator is not an option.

This is my GoRouter Class

class MyAppRouter{

  GoRouter router = GoRouter(

    routes: [
      GoRoute(
          name: MyAppRouteConstants.defaultRouteName,
          path: '/',
          pageBuilder: (context, state){
            return MaterialPage(child: UnknownPage());
          }
      ),
      GoRoute(
        name: MyAppRouteConstants.registerRouteName,
        path: '/register',
        pageBuilder: (context, state){
          return MaterialPage(child: RegisterPage());
        }
      ),
      GoRoute(
          name: MyAppRouteConstants.loginRouteName,
          path: '/login',
          pageBuilder: (context, state){
            return MaterialPage(child: LogInPage());
          }
      ),
      GoRoute(
          name: MyAppRouteConstants.profileRouteName,
          path: '/profile_page',
          pageBuilder: (context, state){
            return MaterialPage(child: HomePage());
          }
      ),
      GoRoute(
          name: MyAppRouteConstants.addRecipeRouteName,
          path: '/add_recipe',
          pageBuilder: (context, state){
            return MaterialPage(child: CreateActivityPage());
          }
      ),
      GoRoute(
          name: MyAppRouteConstants.publicRecipeRouteName,
          path: '/public_recipes',
          pageBuilder: (context, state){
            return MaterialPage(child: PublicRecipePage());
          }
      ),
      GoRoute(
          name: MyAppRouteConstants.favoritesRouteName,
          path: '/favorites',
          pageBuilder: (context, state){
            return MaterialPage(child: FavoritesPage());
          }
      ),
    ],
    errorPageBuilder: (context, state){
      return MaterialPage(child: UnknownPage());
    }

  );
}

I use constants for names, these are the constants, they are in the same file

class MyAppRouteConstants{
  static const String defaultRouteName = 'default';
  static const String registerRouteName = 'register';
  static const String loginRouteName = 'login';
  static const String profileRouteName = 'profile_page';
  static const String addRecipeRouteName = 'add_recipe';
  static const String publicRecipeRouteName = 'public_recipes';
  static const String favoritesRouteName = 'favorites';
}

My main file looks like this:

  runApp(
    OverlaySupport(
      child: MaterialApp.router(
        debugShowCheckedModeBanner: false,
        theme: new ThemeData(scaffoldBackgroundColor: White_Anti_Flash),
        routeInformationParser: MyAppRouter().router.routeInformationParser,
        routerDelegate: MyAppRouter().router.routerDelegate,
        routeInformationProvider: MyAppRouter().router.routeInformationProvider,
      ),
    ),
  );
}

An example I will use is when I push the ProfilePage from LoginPage

This is the function

  void logInUser2(String username, String password, BuildContext context) async {

    if (_formKey.currentState!.validate()) {
      bool userExists = await checkUserExists(usernameController.text);

      if(!userExists){
        showOverlayNotification((context) {
          return CompleteMessage(
            message: 'Username does not exist',
          );
        });
      }
      else{
        showOverlayNotification((context) {
          return CompleteMessage(
            message: 'Log In Successful!',
          );
        });
          final user = await loginUser(usernameController.text, passwordController.text);
         if (user != null) {
           print(user.username);
           context.goNamed(MyAppRouteConstants.profileRouteName);

         }
      }
    }
...(more code)

This function is executed here

TextButton(
          onPressed: () async {
             logInUser2(usernameController.text, passwordController.text, context);
         },
),

Can confirm the line

context.goNamed(MyAppRouteConstants.profileRouteName);

gets executed, I've added print statements before.

I tried go, and push, instead of goNamed, nothing worked. I've putting the line in the onPressed: since the function logInUser2 is async and that may be a problem, but that still did not solve the problem.

I did it as the documentation said, when it comes to navigation, and it should work I think.

1

There are 1 best solutions below

0
On

Inside MaterialApp.router, you passed the router like this:

MaterialApp.router(
  // ...
  routeInformationParser: MyAppRouter().router.routeInformationParser,
  routerDelegate: MyAppRouter().router.routerDelegate,
  routeInformationProvider: MyAppRouter().router.routeInformationProvider,
),

Notice how you called MyAppRouter constructor 3 times, which make each one is a different instance of the class. You might want to do this instead:

MaterialApp.router(
  // ...
  routerConfig: MyAppRouter().router,
),

Or better if you can seperate the instantiation to a variable:

final myAppRouter = MyAppRouter();

and use it like this:

MaterialApp.router(
  // ...
  routerConfig: myAppRouter.router,
),

Or even better if you just make the router a static member of the MyAppRouter class:

class MyAppRouter {

  static GoRouter router = GoRouter(
    // ...
  );
}

and use it like this:

MaterialApp.router(
  // ...
  routerConfig: MyAppRouter.router,
),

Also, check the example usages of GoRouter here: https://github.com/flutter/packages/tree/main/packages/go_router/example/lib