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

GoRouter无法跳转新页面且无报错,寻求解决方案

问题分析与解决方案

问题根源

你的导航请求被GoRouter的redirect逻辑拦截了。每次调用goNamed('setting')时,redirect函数都会优先执行,若当前处于已认证状态(authState != null且authState.freeTrialOpted != null),代码会强制返回/monks,直接覆盖你跳转到setting的请求——这就导致setting路由的builder从未执行,页面不会跳转,也不会产生报错或打印信息。

解决方案

1. 修改redirect逻辑,允许访问设置页面

在redirect中添加判断,排除目标路由为/setting的情况,让已认证用户可以正常跳转:

redirect: (context, state) {
  // 跳过设置页面的重定向检查
  if (state.location == '/setting') {
    return null;
  }

  if (authState != null) {
    if (authState.freeTrialOpted != null) {
      return '/monks';
    } else {
      ref.read(authProvider.notifier).signOut();
      return '/wisdom';
    }
  }
  return null;
},

2. 确保路由响应auth状态变化

你的routerProvider使用普通Provider,当authProvider状态变化时,GoRouter实例不会自动更新。可以通过两种方式修复:

  • 方式一:监听authProvider触发路由重建
final routerProvider = Provider<GoRouter>((ref) {
  final authState = ref.watch(authProvider);
  // 监听auth状态变化,触发Provider重新构建GoRouter
  ref.listen<AuthState?>(authProvider, (_, __) {});

  return GoRouter(
    initialLocation: '/',
    redirect: (context, state) {
      if (state.location == '/setting') {
        return null;
      }
      // 原redirect逻辑不变
      if (authState != null) {
        if (authState.freeTrialOpted != null) {
          return '/monks';
        } else {
          ref.read(authProvider.notifier).signOut();
          return '/wisdom';
        }
      }
      return null;
    },
    routes: [
      GoRoute(
        path: '/',
        builder: (context, state) => const WisdomScreen(),
      ),
      GoRoute(
        path: '/wisdom',
        builder: (context, state) => const WisdomScreen(),
      ),
      GoRoute(
        path: '/monks',
        builder: (context, state) => const MonksScreen(),
      ),
      GoRoute(
        path: '/setting',
        name: 'setting',
        builder: (context, state) {
          print("are we here");
          return SettingsScreen();
        },
      ),
    ],
    errorBuilder: (context, state) => Scaffold(
      body: Center(
        child: Text('Page not found: ${state.location}'),
      ),
    ),
  );
});
  • 方式二:使用refreshListenable(更规范)
    如果你的authProvider是StateNotifierProvider,让AuthNotifier继承ChangeNotifier,然后传入refreshListenable:
final routerProvider = Provider<GoRouter>((ref) {
  final authState = ref.watch(authProvider);
  final authNotifier = ref.watch(authProvider.notifier);

  return GoRouter(
    initialLocation: '/',
    // 当auth状态变化时自动刷新路由
    refreshListenable: authNotifier,
    redirect: (context, state) {
      if (state.location == '/setting') {
        return null;
      }
      // 原redirect逻辑不变
      if (authState != null) {
        if (authState.freeTrialOpted != null) {
          return '/monks';
        } else {
          ref.read(authProvider.notifier).signOut();
          return '/wisdom';
        }
      }
      return null;
    },
    routes: [
      // 你的路由列表
    ],
    errorBuilder: (context, state) => Scaffold(
      body: Center(
        child: Text('Page not found: ${state.location}'),
      ),
    ),
  );
});

验证

修改后,在已认证状态下调用context.goNamed('setting'),redirect会跳过对设置页面的拦截,导航请求会正常触发,setting路由的builder会执行,页面成功跳转。

内容的提问来源于stack exchange,提问作者Sahil Singh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 14:39:51