I realise a Flutter app and I'm a really beginner. I'm using Riverpod for the state management and go_router for the routing. I try to implement a navbar visible only if you are logged. But I think I have a state management issue: when I press a navbar button, nothing happened (no console error neither) but If I logout and login or if I modify my code and save, my Emulator go to the right page. I try to wrap my pages in a bigger Scaffold, to persist the AppBar and NavBar. Here is my main.dart :
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(const ProviderScope(child: MyApp()));
}
class MyApp extends ConsumerWidget {
const MyApp({Key? key}) : super(key: key);
// This widgets is the root of your application.
@override
Widget build(BuildContext context, WidgetRef ref) {
final router = ref.watch(routerProvider);
return MaterialApp.router(
title: 'Ludocal 2',
theme: ThemeData(
primarySwatch: Colors.deepOrange,
),
debugShowCheckedModeBanner: false,
routeInformationProvider: router.routeInformationProvider,
routeInformationParser: router.routeInformationParser,
routerDelegate: router.routerDelegate,
);
}
}
My router :
List<GoRoute> get _routes => [
GoRoute(
name: 'login',
builder: (context, state) => const LoginScreen(),
path: '/login'),
GoRoute(
path: '/:screenName(home|game|event|profile)',
builder: (BuildContext context, GoRouterState state) {
final String screenName = state.params['screenName']!;
return LoggedScreen(screenName: screenName);
})
];
My logged_screen.dart wrapping my other screens :
class LoggedScreen extends HookConsumerWidget {
const LoggedScreen({super.key, required this.screenName});
final String screenName;
@override
Widget build(BuildContext context, WidgetRef ref) {
Future.delayed(Duration.zero, () {
switch (ref.read(indexProvider.state).state) {
case 0:
context.go('/home');
break;
case 1:
context.go('/game');
break;
case 2:
context.go('/event');
break;
case 3:
context.go('/profile');
break;
}
});
return Scaffold(
appBar: AppBar(
title: Text("Ludocal 2"),
backgroundColor: Colors.deepOrangeAccent,
actions: [
TextButton.icon(
icon: Icon(
Icons.logout_rounded,
color: Colors.white,
),
label: Text('', style: TextStyle(color: Colors.white)),
onPressed: () async {
ref.read(loginControllerProvider.notifier).signOut();
},
),
]),
body: BodyTab(screenName: screenName),
bottomNavigationBar: const BottomTab(),
);
}
}
class BodyTab extends ConsumerWidget {
const BodyTab({super.key, required this.screenName});
final String screenName;
@override
Widget build(BuildContext context, WidgetRef ref) {
return Column(
children: [
Expanded(
child: screenName == 'home'
? const HomeScreen()
: screenName == 'game'
? const GameScreen()
: screenName == 'event'
? const EventScreen()
: const ProfileScreen()),
],
);
}
}
class BottomTab extends ConsumerWidget {
const BottomTab({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
return BottomNavigationBar(
currentIndex: ref.read(indexProvider.state).state,
onTap: (int index) => ref.read(indexProvider.state).state = index,
backgroundColor: Colors.deepOrangeAccent,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.emoji_emotions),
label: 'Game',
),
BottomNavigationBarItem(
icon: Icon(Icons.calendar_today_rounded),
label: 'Event',
),
],
);
}
}
final indexProvider = StateProvider<int>((ref) {
return 0;
});
The login_controller.dart :
class LoginController extends StateNotifier<LoginState> {
LoginController(this.ref) : super(const LoginStateInitial());
final Ref ref;
void login(String email, String password) async {
state = const LoginStateLoading();
try {
await ref.read(authRepositoryProvider).signInWithEmailAndPassword(
email,
password,
);
state = const LoginStateSuccess();
} catch (e) {
state = LoginStateError(e.toString());
}
}
void signOut() async {
await ref.read(authRepositoryProvider).signOut();
state = const LoginStateInitial();
}
}
final loginControllerProvider =
StateNotifierProvider<LoginController, LoginState>((ref) {
return LoginController(ref);
});
Thanks for help.
CodePudding user response:
For navigation you need to use listen like below.
ref.listen(indexProvider, (previous, next) {
switch (next) {
case 0:
context.go('/home');
break;
case 1:
context.go('/game');
break;
case 2:
context.go('/event');
break;
case 3:
context.go('/profile');
break;
}
});