go_router中StatefulShellRoute.indexedStack登录后自定义分支不更新问题
解决GoRouter StatefulShellRoute无法根据Firebase自定义权限动态更新分支的问题
问题核心在于你当前的实现中,role是局部变量,通过ref.listen修改它不会触发routes Provider的重建,导致StatefulShellBranch的分支列表始终停留在初始化时的状态(guest角色对应的分支)。要让路由分支随用户权限动态更新,需要让routes Provider直接依赖roleProvider的状态,而非手动修改局部变量。
具体修改步骤
1. 重构路由Provider,让其依赖roleProvider
将原来的局部role变量替换为ref.watch(roleProvider),这样当用户角色变化时,routes Provider会自动重建,生成匹配当前权限的StatefulShellBranch列表:
@riverpod GoRouter routes(RoutesRef ref) { // 直接监听roleProvider的状态,角色变化时自动重建GoRouter final role = ref.watch(roleProvider); return GoRouter( initialLocation: '/signin', redirect: (context, state) { // 保留原有redirect逻辑 ... if(signinSuccess) return '/loader'; ... }, routes: [ GoRoute( path: '/signin', name: 'signin', builder: (_, state) => const SigninView(), ), GoRoute( path: '/loader', name: 'loader', builder: (_, state) => const LoaderView(), ), StatefulShellRoute.indexedStack( builder: (context, state, navigationShell) { return ScaffoldWithNavBar(navigationShell: navigationShell, role: role); }, branches: [ StatefulShellBranch( routes: [ GoRoute( path: '/', name: 'home', builder: (_, state) => const HomeView(), ), ], ), // 现在会根据实时role值动态生成对应权限的分支 if (role == 'admin') StatefulShellBranch( routes: [ GoRoute( path: '/admin', name: 'admin', builder: (_, state) => AdminView(), ), ], ), if (role == 'guest') StatefulShellBranch( routes: [ GoRoute( path: '/foo', name: 'foo', builder: (_, state) => FooView(), ), ], ), ], ), ], ); }
2. 修正LoaderView中的路由刷新逻辑
原来的ref.watch(routesProvider).refresh()是错误的调用方式,若需要强制路由Provider重建(实际上当路由已依赖roleProvider时,此步可省略),应使用ref.invalidate(routesProvider):
@override Widget build(BuildContext context, WidgetRef ref) { ref.listen(loaderProvider, (previous, loadingDone) { if(loadingDone.valueOrNull == true) { // 可选:强制路由Provider重建(若路由已依赖roleProvider则无需此操作) ref.invalidate(routesProvider); context.goNamed('home'); } }); return Scaffold( body: SizedBox(...), ); }
为什么这样能解决问题
ref.watch(roleProvider)会让routesProvider订阅roleProvider的状态变化,一旦用户权限更新,Provider会立即重建,生成包含对应权限分支的新GoRouter实例。- 原来的
ref.listen仅修改局部变量,不会触发Provider重建,所以路由分支始终停留在初始化时的版本。
内容的提问来源于stack exchange,提问作者enchance
相关产品推荐
相关产品推荐

