Flutter Web使用go_router登录后重定向异常:isLoggedIn始终为false
问题排查与修复方案
你的问题核心是登录成功后,GoRouter的redirect方法中authState.isLoggedIn仍为false,主要可能是以下几个原因:
1. AuthProvider实例不一致
如果生成路由时传入的AuthProvider实例,和登录页面中使用的不是同一个全局实例,就会导致路由监听的状态没有更新。必须确保整个App中使用的是同一个AuthProvider实例。
修复方式:
通过Provider将AuthProvider全局注入,生成路由时从全局Provider获取实例,而非手动创建新实例:
// main.dart void main() { runApp( ChangeNotifierProvider( create: (_) => AuthProvider(), child: MyApp(), ), ); } // 路由生成函数修改为从Provider获取实例 GoRouter routerGenerator(BuildContext context) { final authState = Provider.of<AuthProvider>(context, listen: false); return GoRouter( initialLocation: Routes.login, refreshListenable: authState, redirect: (state) { final isOnLogin = state.location == Routes.login; final isOnSignUp = state.location == Routes.signup; final isLoggedIn = authState.isLoggedIn; if (!isOnLogin && !isOnSignUp && !isLoggedIn) return Routes.login; if ((isOnLogin || isOnSignUp) && isLoggedIn) return Routes.home; return null; }, routes: [ GoRoute( name: Routes.home, path: '/Dashboard', pageBuilder: (context, state) => MaterialPage<void>( key: state.pageKey, child: Home(), ), ), // 补充登录、注册路由定义 GoRoute( name: Routes.login, path: '/login', pageBuilder: (context, state) => MaterialPage<void>( key: state.pageKey, child: LoginPage(), ), ), GoRoute( name: Routes.signup, path: '/signup', pageBuilder: (context, state) => MaterialPage<void>( key: state.pageKey, child: SignUpPage(), ), ), ], ); }
2. 状态更新未正确通知监听者
虽然你在login方法中调用了notifyListeners(),但loggedIn setter本身没有触发通知,后续如果在其他地方修改loggedIn时容易遗漏通知。建议将通知逻辑整合到setter中:
修复AuthProvider:
class AuthProvider extends ChangeNotifier { bool _isLoggedIn = false; bool get isLoggedIn => _isLoggedIn; set loggedIn(bool value) { _isLoggedIn = value; notifyListeners(); // 赋值时自动通知监听者 } ApiBaseHelper _helper = ApiBaseHelper(); Future<Map<String, dynamic>> login(String email, String password) async { var response = await _helper.post( 'Authentication/Login', LoginVM(username: email, password: password, otp: '') ); this.loggedIn = true; // 这里无需再手动调用notifyListeners(),setter已处理 return response; } }
3. 登录操作未等待异步完成
登录按钮点击时,必须确保await登录异步操作完成,保证状态更新后再触发路由刷新:
登录页面示例:
class LoginPage extends StatelessWidget { @override Widget build(BuildContext context) { final authProvider = Provider.of<AuthProvider>(context); return Scaffold( body: ElevatedButton( onPressed: () async { // 等待登录请求完成,确保状态更新 await authProvider.login('your-email', 'your-password'); // 无需手动跳转,GoRouter的redirect会自动处理 }, child: const Text('登录'), ), ); } }
额外检查
- 确认
Routes.login、Routes.signup的字符串值和路由定义中的path完全一致,避免因路径不匹配导致判断错误。 - 确保
refreshListenable: authState已正确设置,这样AuthProvider状态变化时会触发GoRouter重新执行redirect逻辑。
内容的提问来源于stack exchange,提问作者Salman Akbar
相关产品推荐
相关产品推荐

