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

Flutter GoRouter中跳转ShellRoute的replace方法异常问题求助

问题解决:GoRouter ShellRoute 未构建且页面未替换的问题

问题根源

  1. 路由结构错误:当前ShellRoute与根路径/的GoRoute平级,/somepage1作为根级路由直接由根导航器处理,不会触发Shell组件的构建。
  2. 跳转逻辑未匹配路由结构:context.replace('/somepage1')仅替换根导航栈页面,但由于目标路由不属于ShellRoute的嵌套范围,无法加载Shell。

解决方案

调整路由结构,给ShellRoute设置父路径,将somepage1、somepage2作为其嵌套子路由,确保跳转时触发Shell的构建并替换根页面。

修改后的完整代码

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

void main() => runApp(const MyApp());

final GlobalKey<NavigatorState> rootNavKey = GlobalKey<NavigatorState>();
final GlobalKey<NavigatorState> shellNavKey = GlobalKey<NavigatorState>();

final GoRouter router = GoRouter(
  navigatorKey: rootNavKey,
  initialLocation: '/',
  routes: [
    GoRoute(
      path: '/',
      pageBuilder: (context, state) => const NoTransitionPage(child: Home()),
    ),
    // 给ShellRoute设置父路径/app,作为嵌套路由的容器
    ShellRoute(
      navigatorKey: shellNavKey,
      parentNavigatorKey: rootNavKey,
      routes: [
        // 子路由使用相对路径,完整路径为/app/somepage1
        GoRoute(
          path: 'somepage1',
          pageBuilder: (context, state) => const NoTransitionPage(child: SomePage1()),
        ),
        GoRoute(
          path: 'somepage2',
          pageBuilder: (context, state) => const NoTransitionPage(child: SomePage2()),
        ),
      ],
      builder: (context, state, child) => Shell(state: state, child: child),
    ),
    // 添加ShellRoute的入口路由,对应路径/app
    GoRoute(
      path: '/app',
      redirect: (context, state) => '/app/somepage1',
    ),
  ],
);

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerConfig: router,
    );
  }
}

class Shell extends StatelessWidget {
  Shell({super.key, required this.state, required this.child}) {
    print('Shell: ${state.location}');
  }

  final GoRouterState state;
  final Widget child;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Row(
        children: [
          Container(
            width: 300.0,
            color: Colors.black,
            padding: const EdgeInsets.all(16),
            child: Column(
              children: [
                ListTile(
                  onTap: () => context.go('/app/somepage1'),
                  title: const Text('Go to SomePage 1', style: TextStyle(color: Colors.white)),
                ),
                ListTile(
                  onTap: () => context.go('/app/somepage2'),
                  title: const Text('Go to SomePage 2', style: TextStyle(color: Colors.white)),
                ),
              ],
            ),
          ),
          Expanded(child: child),
        ],
      ),
    );
  }
}

class Home extends StatelessWidget {
  const Home({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: InkWell(
          // 跳转到ShellRoute的入口路径,替换当前根页面
          onTap: () => context.replace('/app/somepage1'),
          child: const Text('Click!'),
        ),
      ),
    );
  }
}

class SomePage1 extends StatelessWidget {
  const SomePage1({super.key});

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(
        child: Text('Some Page 1'),
      ),
    );
  }
}

class SomePage2 extends StatelessWidget {
  const SomePage2({super.key});

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(
        child: Text('Some Page 2'),
      ),
    );
  }
}

关键修改点

  • 给ShellRoute绑定父路径/app,子路由使用相对路径,确保/app/somepage1、/app/somepage2属于ShellRoute的嵌套范围。
  • 修改Home页面的跳转目标为/app/somepage1,使用context.replace替换根导航栈,移除原来的Home页面。
  • 侧边栏的跳转路径更新为完整的/app/somepage1、/app/somepage2,确保在Shell的嵌套导航器中切换页面。

实现效果

  1. 点击Home的"Click!"后,根导航栈中的Home页面被替换,Shell组件和SomePage1同时加载。
  2. 侧边栏切换页面时,仅更新Shell右侧的内容区域,Shell保持存在,符合嵌套路由的预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 06:37:53