The app is giving the following error: " (pageBuilder != null) ^ (builder != null) One of builder or pageBuilder must be provided, but not both" when running.

This is my main function

Future<void> main() async {

  WidgetsFlutterBinding.ensureInitialized();
  final sharedPreferences = await SharedPreferences.getInstance();

  await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);

  // import flutter_web_plugings/url_strategy.dart
  // usePathUrlStrategy();
  runApp(const ProviderScope(child: MyApp()));

  // runApp(SidebarXExampleApp());
}

here is the Root widget :

class MyApp extends ConsumerWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context, WidgetRef ref) {

    final goRouter  = ref.watch(goRouterProvider);

    return MaterialApp.router(
      routerConfig: goRouter,
      title: 'ARPTC',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      // routerDelegate: ref.watch(goRouterProvider).routerDelegate,
      // routeInformationParser: ref.watch(goRouterProvider).routeInformationParser,
      // home: const AuthCheckerScreen(),
    );
  }
}

And here is the provider for goRouter (I have commented the redirect logic for the time being to simplify the app and make it run first) :

final goRouterProvider = Provider<GoRouter>((ref) {

  final rootNavigatorKey = GlobalKey<NavigatorState>();
  final _shellNavigatorAKey = GlobalKey<NavigatorState>(debugLabel: 'shellA');
  final _shellNavigatorBKey = GlobalKey<NavigatorState>(debugLabel: 'shellB');

  return GoRouter(
    initialLocation: '/dashboard',
    navigatorKey: rootNavigatorKey,
    debugLogDiagnostics: true,
    routes: [
      StatefulShellRoute.indexedStack(
        branches: [
          StatefulShellBranch(
            navigatorKey: _shellNavigatorAKey,
            routes: [
              GoRoute(
                path: '/a',
                pageBuilder: (context, state) => const NoTransitionPage(
                  child: RootScreen(label: 'A', detailsPath: '/a/details'),
                ),
                routes: [
                  GoRoute(
                    path: 'details',
                    builder: (context, state) => const DetailsScreen(label: 'A'),
                  ),
                ],
              ),
            ],
          ),
          StatefulShellBranch(
            navigatorKey: _shellNavigatorBKey,
            routes: [
              // Shopping Cart
              GoRoute(
                path: '/b',
                pageBuilder: (context, state) => const NoTransitionPage(
                  child: RootScreen(label: 'B', detailsPath: '/b/details'),
                ),
                routes: [
                  GoRoute(
                    path: 'details',
                    builder: (context, state) => const DetailsScreen(label: 'B'),
                  ),
                ],
              ),
            ],
          ),
        ],
      )
    ],
    redirect: (context, state)  {

      // final _authState = ref.watch(authStateProvider);

      // return _authState.when(
      //     data: (data) {
      //       print("DATA ==> $data");
      //       User? user = data;
      //
      //       if (user == null){
      //         debugPrint(":: RETURNING DASHBOARD");
      //         return '/login';
      //       }
      //       // debugPrint(":: RETURNING LOGIN");
      //       // return '/login';
      //     },
      //     loading: () => '/login',
      //     error: (e, trace) => '/error');


    },
  );
}
);

But when I use simple the following GoRouter without StatefullShellRoute it works :

final goRouterProviderTwo = Provider<GoRouter>((ref){
  return router(ref);
});

GoRouter router(ProviderRef ref) {

final rootNavigatorKey = GlobalKey<NavigatorState>();
  final shellNavigatorCourrierKey =
      GlobalKey<NavigatorState>(debugLabel: 'shellCourrier');
  final shellNavigatorDashboardKey =
      GlobalKey<NavigatorState>(debugLabel: 'shellDashboard');
  final shellNavigatorErrorKey =
      GlobalKey<NavigatorState>(debugLabel: 'shellError');
  final shellNavigatorLoginKey =
      GlobalKey<NavigatorState>(debugLabel: 'shellLogin');

  return GoRouter(
    initialLocation: '/courriers',
    navigatorKey: rootNavigatorKey,
    debugLogDiagnostics: true,
    routes: [
      GoRoute(
        path: '/login',
        pageBuilder: (context, state) => const NoTransitionPage(
          child: LoginScreen(),
        ),
      ),
      GoRoute(
        path: '/dashboard',
        pageBuilder: (context, state) => const NoTransitionPage(
          child: DashboardPage(),
        ),
      ),
      GoRoute(
        path: '/courriers',
        pageBuilder: (context, state) => const NoTransitionPage(
          child: ListCourriersScreen(),
        ),
        // routes: [
        //   GoRoute(
        //     path: 'details/:courrierId',
        //     pageBuilder: (context, state) {
        //
        //       return NoTransitionPage(
        //           child: DetailsCourrierScreen(state.pathParameters['courrierId'] as String));
        //     },
        //   ),
        // ],
      ),
      GoRoute(
        path: '/courriers/:courrierId',
        pageBuilder: (context, state) {

          return NoTransitionPage(
              child: DetailsCourrierScreen(state.pathParameters['courrierId'] as String));
        },
      ),
      GoRoute(
        path: '/error',
        pageBuilder: (context, state) => const NoTransitionPage(
          child: Center(
            child: Text('Error'),
          ),
        ),
      )
    ],
    redirect: (context, state) async {

      final _authState = ref.watch(authStateProvider);

      return _authState.when(
          data: (data) {
            User? user = data;

            // if (user == null && state.location == '/'){
            if (user == null ){
              debugPrint(":: GO TO LOGIN SCREEN");
              return '/login';
            }
            // debugPrint(":: RETURNING LOGIN");
            // return '/login';
          },
          loading: () => '/login',
          error: (e, trace) => '/error');

    },
  );
}

Any idea why the GoRouter with StatefullShellRoute not working with riverpod ?

1

There are 1 best solutions below

1
On BEST ANSWER

The assert uses a XOR to validate pageBuilder or builder (only one can be passed, both or none fails the assert) and it seems you're not providing any:

StatefulShellRoute(
   pageBuilder: ///pass this,
   builder: ///or this,
   routes: [...],
)