GoRouter重定向时获取当前路由,避免Auth页面重复导航
问题场景
- 应用内通过
pushNamed('auth')跳转至登录页面 - 登录邮件包含深度链接
"/auth?token=XXX",点击后需处理登录令牌 - 需求:若当前已在auth页面,点击链接时不执行导航(避免重置导航栈),仅传递令牌;否则正常跳转至auth页面
现有实现思路(待完善)
return GoRouter( initialLocation: '/', debugLogDiagnostics: kDebugMode, redirect: (context, state) async { // 需要判断当前是否在auth页面 final currentlyOnAuth = XXXX final isRequestingAuthPage = state.uri.matchedLocation == "auth" if (currentlyOnAuth && isRequestingAuthPage) { // 将令牌传递给控制器 throw // 阻止导航 } } )
已尝试方案(无效)
- 在全局或auth路由的
redirect方法中,尝试通过GoRouter.of(context).routerDelegate.currentConfiguration.last获取当前路由,但无法访问 - 在auth路由的routeBuilder中做同样尝试,也无法获取
简洁解决方案
不需要额外路由监听器或第三方库,直接利用GoRouter的redirect机制结合当前路由位置判断:
步骤1:定义令牌传递的全局状态(或用Provider/Bloc)
// 用于在redirect和auth页面间传递令牌 final authTokenNotifier = ValueNotifier<String?>(null);
步骤2:完善GoRouter的redirect逻辑
return GoRouter( initialLocation: '/', debugLogDiagnostics: kDebugMode, redirect: (context, state) { final currentLocation = GoRouter.of(context).location; final isRequestingAuth = state.uri.matchedLocation == '/auth'; // 判断当前是否已在auth页面(兼容带参数的情况) final isAlreadyOnAuth = currentLocation.startsWith('/auth'); if (isRequestingAuth && isAlreadyOnAuth) { // 从深度链接中提取令牌 final token = state.uri.queryParameters['token']; if (token != null) { // 将令牌传递给auth页面 authTokenNotifier.value = token; } // 返回当前位置,阻止导航操作 return currentLocation; } // 其他路由逻辑,无redirect则返回null return null; }, routes: [ GoRoute( path: '/', builder: (context, state) => HomePage(), ), GoRoute( path: '/auth', builder: (context, state) => AuthPage(), ), ], );
步骤3:在Auth页面监听令牌并处理
class AuthPage extends StatelessWidget { @override Widget build(BuildContext context) { return ValueListenableBuilder<String?>( valueListenable: authTokenNotifier, builder: (context, token, child) { if (token != null) { // 触发登录逻辑,比如调用控制器处理令牌 WidgetsBinding.instance.addPostFrameCallback((_) { // 处理完成后清空令牌,避免重复触发 authTokenNotifier.value = null; }); } return Scaffold( appBar: AppBar(title: Text('登录')), body: Center( // 登录页面UI,比如申请登录邮件的按钮 child: ElevatedButton( onPressed: () => _sendLoginEmail(), child: Text('发送登录邮件'), ), ), ); }, ); } void _sendLoginEmail() { // 发送登录邮件的逻辑 } }
方案说明
GoRouter.of(context).location在redirect函数中可正常访问,能准确获取当前路由位置,无需额外监听- 通过
ValueNotifier实现令牌的跨组件传递,替代复杂的状态管理方案 - 返回当前位置给redirect函数,GoRouter会放弃本次导航,避免重置导航栈
内容的提问来源于stack exchange,提问作者Nicolas Braun
相关产品推荐
相关产品推荐

