Skip to content

GoRouter does not preserve browser URL if app widget rebuilds the router during build() #172026

@jcairney-UHN

Description

@jcairney-UHN

Steps to reproduce

Using go_router ^16.0.0 or ^15.1.1

  1. Run the attached sample code: flutter run -d chrome. The URL resolves from / to /home.
  2. Click the "Go to Second Page" button. The URL changes from /home to /second-page.
  3. Refresh the page using the browser's refresh button. Route changes from /second-page to /home

This example is greatly simplified, but mimics wrapping your app widget class in Riverpod's ProviderScope (runApp(ProviderScope(child: AppWidget()));) which may rebuild the app widget due to changes in providers, after the first time the router properly resolves to the current URL.

Expected results

The page loads and stays at /second-page

Actual results

The page redirects back to /home

Code sample

Code sample
import 'package:flutter/material.dart';
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
import 'package:go_router/go_router.dart';

void main() {
  usePathUrlStrategy();
  runApp(MyApp());
}

/**
 * Steps to replicate the issue:
 * 1. Run the app: `flutter run -d chrome`.  The URL resolves from / to /home.
 * 2. Click the "Go to Second Page" button.  The URL changes from /home to /second-page.
 * 3. Refresh the page using the browser's refresh button.
 * 
 * I'm seeing /second-page load, but then the app redirects to /home after a second. 
 */

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

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {}));
  }

  @override
  Widget build(BuildContext context) {
    print("rebuilding MyApp");
    GoRouter router = GoRouter(
      debugLogDiagnostics: true,
      initialLocation: '/',
      routes: [
        GoRoute(
          path: '/',
          redirect: (context, state) => MyHomePage.routeName,
        ),
        GoRoute(
          path: MyHomePage.routeName,
          builder: (context, state) => MyHomePage(title: 'Flutter Demo Home Page'),
        ),
        GoRoute(
          path: SecondPage.routeName,
          builder: (context, state) => SecondPage(title: 'Second Page'),
        ),
      ],
    );

    return MaterialApp.router(
      title: 'Flutter Demo',
      theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple)),
      routerConfig: router,
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  static const routeName = '/home';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(backgroundColor: Theme.of(context).colorScheme.inversePrimary, title: Text(title)),
      body: Center(
        child: TextButton(
          child: const Text('Go to Second Page'),
          onPressed: () {
            context.go(SecondPage.routeName);
          },
        ),
      ),
    );
  }
}

class SecondPage extends StatelessWidget {
  const SecondPage({super.key, required this.title});

  final String title;

  static const routeName = '/second-page';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(backgroundColor: Theme.of(context).colorScheme.inversePrimary, title: Text(title)),
      body: Center(child: Text(title)),
    );
  }
}

Screenshots or Video

Screenshots / Video demonstration

[Upload media here]

Logs

Logs
rebuilding MyApp
rebuilding MyApp
[GoRouter] Full paths for routes:
           ├─/ 
           ├─/home (MyHomePage)
           └─/second-page (SecondPage)
[GoRouter] setting initial location /
[GoRouter] redirecting to RouteMatchList#a9568(uri: /home, matches: [RouteMatch#5b644(route: GoRoute#bac59(name: null, path: "/home"))])
[GoRouter] Using MaterialApp configuration
[GoRouter] Full paths for routes:
           ├─/ 
           ├─/home (MyHomePage)
           └─/second-page (SecondPage)
[GoRouter] setting initial location /
[GoRouter] redirecting to RouteMatchList#dbd33(uri: /home, matches: [RouteMatch#0f1d2(route: GoRoute#a044e(name: null, path: "/home"))])
[GoRouter] Using MaterialApp configuration
[GoRouter] going to /second-page
rebuilding MyApp
rebuilding MyApp
[GoRouter] Full paths for routes:
           ├─/ 
           ├─/home (MyHomePage)
           └─/second-page (SecondPage)
[GoRouter] setting initial location /
[GoRouter] Using MaterialApp configuration
[GoRouter] Full paths for routes:
           ├─/ 
           ├─/home (MyHomePage)
           └─/second-page (SecondPage)
[GoRouter] setting initial location /
[GoRouter] redirecting to RouteMatchList#efbee(uri: /home, matches: [RouteMatch#d78f0(route: GoRoute#7edbe(name: null, path: "/home"))])
[GoRouter] Using MaterialApp configuration

Flutter Doctor output

Doctor output
[✓] Flutter (Channel stable, 3.32.0, on macOS 14.5 23F79 darwin-arm64, locale en-CA) [943ms]
    • Flutter version 3.32.0 on channel stable at /opt/homebrew/Caskroom/flutter/3.29.0/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision be698c48a6 (8 weeks ago), 2025-05-19 12:59:14 -0700
    • Engine revision 1881800949
    • Dart version 3.8.0
    • DevTools version 2.45.1

[✓] Chrome - develop for the web [256ms]
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] VS Code (version 1.101.2) [255ms]
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.114.0

[✓] Connected device (2 available) [6.4s]
    • iPhone SE (3rd generation) (mobile) • 51DF3FD4-8F1E-4047-90BA-A1B94513C904 • ios            • com.apple.CoreSimulator.SimRuntime.iOS-18-3 (simulator)
    • Chrome (web)                        • chrome                               • web-javascript • Google Chrome 138.0.7204.101
    ! Error: Browsing on the local area network for Joel’s iPhone. Ensure the device is unlocked and attached with a cable or associated with the same local
      area network as this Mac.
      The device must be opted into Developer Mode to connect wirelessly. (code -27)
    ! Error: Browsing on the local area network for Joel’s Apple Watch. Ensure the device is unlocked and discoverable via Bluetooth. (code -27)

[✓] Network resources [268ms]
    • All expected network resources are available.

• No issues found!

Metadata

Metadata

Assignees

No one assigned

    Labels

    found in release: 3.32Found to occur in 3.32found in release: 3.33Found to occur in 3.33has reproducible stepsThe issue has been confirmed reproducible and is ready to work onp: go_routerThe go_router packagepackageflutter/packages repository. See also p: labels.team-frameworkOwned by Framework team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      pFad - Phonifier reborn

      Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

      Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


      Alternative Proxies:

      Alternative Proxy

      pFad Proxy

      pFad v3 Proxy

      pFad v4 Proxy