You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 07:57:26