如何在GoRouter中重写URL?处理带query参数的跳转传参问题
解决方案
方案一:利用全局Redirect(URL保留query参数)
直接在GoRouter的根路由配置redirect逻辑,处理根路径的query参数并重定向到目标路由,同时携带参数:
final goRouter = GoRouter( routes: [ GoRoute( path: '/', // 全局处理根路径的重定向逻辑 redirect: (context, state) { final queryValue = state.queryParams['query']; if (queryValue != null) { // 重定向到/query并携带query参数 return '/query?query=$queryValue'; } return null; // 无参数时正常显示根页面 }, builder: (context, state) => const HomeScreen(), ), GoRoute( name: 'query', path: '/query', builder: (context, state) { // 从queryParams中获取参数 final query = state.queryParams['query'] ?? ''; return QueryScreen(query: query); }, ), ], );
这个方案逻辑集中在路由配置中,无需额外组件包装,完全符合GoRouter设计规范,不会出现上下文找不到GoRouter的问题。
方案二:根路由Builder中直接跳转(URL不保留参数,用extra传递)
如果希望重定向后URL不显示query参数,可在根路由的builder中通过GoRouter.of(context)主动跳转,避免直接使用context.goNamed导致的上下文问题:
final goRouter = GoRouter( routes: [ GoRoute( path: '/', builder: (context, state) { final queryValue = state.queryParams['query']; if (queryValue != null) { // 直接获取全局GoRouter实例进行跳转,传递extra参数 GoRouter.of(context).goNamed('query', extra: queryValue); // 返回临时空页面,因为跳转后会立即替换当前页面 return const Scaffold(body: SizedBox.shrink()); } return const HomeScreen(); }, ), GoRoute( name: 'query', path: '/query', builder: (context, state) { // 从extra中获取参数,注意判空处理 final query = state.extra?.toString() ?? ''; return QueryScreen(query: query); }, ), ], );
为什么之前的方法失效?
- 在其他路由的
builder中执行跳转:此时该builder的上下文尚未被GoRouter的InheritedWidget覆盖,无法找到GoRouter实例,因此报错No GoRouter found in context。 initState中延迟跳转:initState执行时Widget尚未完全挂载到Widget树,即使延迟,上下文仍可能未包含GoRouter的全局实例,导致跳转失败。
内容的提问来源于stack exchange,提问作者Adrien Lemaire
相关产品推荐
相关产品推荐

