7

I have wrapped the MaterialApp with a BlocProvider / BlocListener

I get an error

"Unhandled Exception: 'package:go_router/src/router.dart': Failed assertion: line 280 pos 12: 'inherited != null': No GoRouter found in context" from the Listener callback
Widget build(BuildContext context) {
    return BlocProvider<AuthenticationBloc>(
      create: (context) => AuthenticationBloc()..add(AppStarted()),
      child: BlocListener<AuthenticationBloc, AuthenticationState>(
        listener: (context, state) {
          if (state is AuthenticationUnauthenticated) {
            context.goNamed(LoginPage.routeName);
          }
          if (state is AuthenticationAuthenticated) {
            context.goNamed(NavigationBarContainer.routeName);
          }
        },
        child: MaterialApp.router(
            title: 'Flutter Demo',
            routeInformationProvider: _router.routeInformationProvider,
            routeInformationParser: _router.routeInformationParser,
            routerDelegate: _router.routerDelegate,
            theme: ThemeData(
              primarySwatch: Colors.blue,
            )),
      ),
    );
  }
krishnaacharyaa
  • 14,953
  • 4
  • 49
  • 88
fvisticot
  • 7,936
  • 14
  • 49
  • 79
  • [This looks like what we want](https://docs.page/csells/go_router/navigator-builder) but it seems to have been taken away from the latest version. Checking the [change logs](https://docs.google.com/document/d/10l22o4ml4Ss83UyzqUC8_xYOv_QjZEi80lJDNE4q7wM/edit?pli=1&resourcekey=0-U-BXBQzNfkk4v241Ow-vZg#) it says to use `MaterialApp.builder`, which I have done, but I still have the same error. – BeniaminoBaggins Jan 02 '23 at 08:17
  • Just use router.go('/route_name') instead of context.go('route_name') – ramluro Feb 15 '23 at 00:02

2 Answers2

2

You are attempting to navigate with context from higher up in the widget tree than go_router gets inserted.

I don't know where your GoRouter() routerConfig is, and where it is called from when you use a RouterDelegate, (maybe you don't need to use a delegate?) but you need to call your GoRouter configuration directly, and navigate from that.

So you need to change:

context.goNamed(LoginPage.routeName)

to

routerConfig.goNamed(LoginPage.routeName)

For me, you can see I pass the routerConfig to MaterialApp.router, and I also navigate directly from that, with routerConfig.go(HOME), from above the MaterialApp:

    ref.watch(authStatusServiceProvider).whenData((authStatus) {
      switch (authStatus) {
        case AuthenticationStatusEnum.authenticated:
          routerConfig.go(HOME);
          break;
        case AuthenticationStatusEnum.unauthenticated:
          routerConfig.go(LOGGED_OUT_HOME);
          break;
        default:
          routerConfig.go(LOGGED_OUT_HOME);
          break;
      }
    });

    return MaterialApp.router(
      theme: lightTheme,
      debugShowCheckedModeBanner: false,
      darkTheme: darkTheme,
      routerConfig: routerConfig,
    );
  }

All credit goes to darshankawar on Github.

BeniaminoBaggins
  • 11,202
  • 41
  • 152
  • 287
0

This is happening because you are using context of go_router before it is initialized !!

Widget build(BuildContext context) {
    return BlocProvider<AuthenticationBloc>(
      create: (context) => AuthenticationBloc()..add(AppStarted()),
      child: BlocListener<AuthenticationBloc, AuthenticationState>(
        listener: (context, state) {
          if (state is AuthenticationUnauthenticated) {
            context.goNamed(LoginPage.routeName);              //  Go router is not initilaized yet
          }
          if (state is AuthenticationAuthenticated) {
            context.goNamed(NavigationBarContainer.routeName); //  Go router is not initilaized yet
          }
        },
        child: MaterialApp.router(
            routeInformationProvider: _router.routeInformationProvider,
            routeInformationParser: _router.routeInformationParser,
            routerDelegate: _router.routerDelegate,            //  Your router is initialized here
      ),
    );
  }

Make changes to :

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MultiBlocProvider(
        providers: [
          BlocProvider<AuthenticationBloc>(
            create: (context) => AuthenticationBloc()..add(AppStarted()),  Specify only the BlocProvider here
          ),
        ],
        child: MaterialApp(
            theme: customTheme(context),
            debugShowCheckedModeBanner: false,
            routeInformationProvider: _router.routeInformationProvider,
            routeInformationParser: _router.routeInformationParser,
            routerConfig: router,
  }

And then try to navigate inside the routerlike:

final GoRouter router = GoRouter(routes: [
  GoRoute(
      path: "/",
      builder: (context, state) {
        return BlocBuilder<AuthCubit, AuthState>(
          buildWhen: (oldState, newState) {
            return oldState is AuthInitialState;
           },
          builder: (context, state) {
            if (state is AuthenticationUnauthenticated) {
              // return const LoginPage();                         // alternative way
               context.goNamed(LoginPage.routeName);                Use conditional routing using context here 
            } else if (state is NavigationBarContainer.routeName) {
              // return SignIn();                                 // alternative way
                context.goNamed(NavigationBarContainer.routeName);  Use conditional routing using context here 
            } else {
              return const Scaffold();
            }
          },
        );
      }),
krishnaacharyaa
  • 14,953
  • 4
  • 49
  • 88
  • MaterialApp has none of the router... named parameters you have typed here, so this code does not work. – macasas May 28 '23 at 08:23
  • Well then @macasas, the question should be invalid, because question also shouldn't have any "router... named parameters" as you strongly claimed :) – krishnaacharyaa May 28 '23 at 10:12
  • I would have thought a question was allowed to be "wrong" and "invalid" because that's why the person is asking for help. I would have also thought it better to provide an answer that works. Providing an answer that doesn't work and then claiming you did it because the question doesn't work, sounds like you might be here for the wrong reasons, and as I see you have bounced all over this page telling others you don't "think" their answers work, I would "strongly" suggest you review your motivations. – macasas May 29 '23 at 11:45