I'm trying to manage routes in my application using goRouter and Riverpod, and everything is working perfectly except for the navBar. I have a state provider that helps me display which item is currently being shown by the router (just an integer). I'm trying to modify this state in my goRouter provider when calling the redirect function but without success.
Here's the problem: when I call "ref.read(navBarIndexProvider.notifier).state = myTabId;" in my redirect function, the state change is not detected in BottomNavBarItem (it is detected in goRouterProvider). Conversely, when I call "ref.read(navBarIndexProvider.notifier).state = myIntValue" from my BottomNavBarItem widget, the state change is not detected in goRouterProvider. I have the feeling that there are two instances of my navBarIndexProvider, but I'm not sure if that's possible and, if it is, I wonder why.
I'm using Flutter 3.10.5 dart Dart 3.0.5 flutter_riverpod: ^2.3.10 go_router: ^9.0.3
In short, I am completely lost, and if anyone has an idea, I'd appreciate it.
Thanks in advance
My index provider :
final navBarIndexProvider = StateProvider<int>((ref) {
return 0;
});
My navbar item
class BottomNavBarItem extends ConsumerWidget {
const BottomNavBarItem({required this.icon, required this.path, required this.index, super.key});
final IconData icon;
final String path;
final int index;
@override
Widget build(BuildContext context, WidgetRef ref) {
int navBarIndexState = ref.watch(navBarIndexProvider);
void onItemTapped() {
//ref.read(navBarIndexProvider.notifier).state = index;
context.go(path);
}
return
IconButton(
enableFeedback: false,
onPressed: () => onItemTapped(),
icon: Icon(
icon,
color: navBarIndexState == index ? AppColors.primaryDarkest : Colors.white,
size: 30,
),
);
}
}
Here my GoRouterProvider
final goRouterProvider = Provider<GoRouter>((ref) {
final GlobalKey<NavigatorState> rootNavigatorKey = GlobalKey<NavigatorState>();
final GlobalKey<NavigatorState> shellNavigatorKey = GlobalKey<NavigatorState>();
String? redirect(BuildContext context, GoRouterState state) {
final String destination = state.location;
print('Before update : ${ref.read(navBarIndexProvider)}');
print(destination);
if (destination == '/') {
ref.read(navBarIndexProvider.notifier).state = 0;
}
if (destination == '/page1') {
ref.read(navBarIndexProvider.notifier).state = 1;
}
if (destination == '/page2') {
ref.read(navBarIndexProvider.notifier).state = 2;
}
print('After udpdate : ${ref.read(navBarIndexProvider)}');
return null;
}
return GoRouter(
initialLocation: '/',
navigatorKey: rootNavigatorKey,
redirect: redirect,
routes: [
ShellRoute(
navigatorKey: shellNavigatorKey,
pageBuilder: (BuildContext context, GoRouterState state, Widget child) {
return NoTransitionPage(
child: Scaffold(
extendBody: true,
body: child,
bottomNavigationBar: const MyBottomNavBar(),
),
);
},
routes: [
GoRoute(
path: '/',
parentNavigatorKey: shellNavigatorKey,
pageBuilder: (context, state) => const NoTransitionPage(child: HomePage()),
),
GoRoute(
path: '/page1',
parentNavigatorKey: shellNavigatorKey,
pageBuilder: (context, state) => const NoTransitionPage(child: SwipePage()),
),
//...
],),
],
);
});
My main function
Future<void> main() async {
//...
//Riverpods
final container = ProviderContainer();
runApp(
ProviderScope(
parent: container,
child:
BlocProvider(
create: (context) => PaymentBloc(),
child: p.MultiProvider(
providers: [
p.ChangeNotifierProvider(
create: (_) => AuthProvider(),
),
],
child: const MyApp(),
),
),
),
);
}
I call my app router like this
class MyApp extends ConsumerStatefulWidget {
const MyApp({super.key});
@override
ConsumerState<MyApp> createState() => _MyAppState();
}
class _MyAppState extends ConsumerState<MyApp> {
@override
Widget build(BuildContext context) {
final router = ref.watch(goRouterProvider);
return MaterialApp.router(
//Router
routerConfig: router);
}
}