-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Open
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work listfound in release: 3.22Found to occur in 3.22Found to occur in 3.22found in release: 3.23Found to occur in 3.23Found to occur in 3.23has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onp: go_routerThe go_router packageThe go_router packagepackageflutter/packages repository. See also p: labels.flutter/packages repository. See also p: labels.platform-webWeb applications specificallyWeb applications specificallyteam-frameworkOwned by Framework teamOwned by Framework teamtriaged-frameworkTriaged by Framework teamTriaged by Framework team
Description
Steps to reproduce
In the given sample:
- Press Push on the root screen
- Press push again on route A
- Press "Go Back" on screen B
Expected results
The screen is popped and the URL is updated
Actual results
The screen is popped and the URL is still /#/a/b on web. This only happens if counterStream.increment(); is called just before popping. If it's omitted, then everything works as expected.
Code sample
Code sample
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
class CounterStream {
int _counter = 0;
final _streamController = StreamController<int>.broadcast();
Stream<int> get stateStream => _streamController.stream.asBroadcastStream();
void increment() {
_streamController.sink.add(++_counter);
}
Future<void> delayedRerender() async {
increment();
increment();
}
void dispose() {
_streamController.close();
}
}
final CounterStream counterStream = CounterStream();
class StreamListener extends ChangeNotifier {
StreamListener(Stream<dynamic> stream) {
notifyListeners();
_subscription = stream.asBroadcastStream().listen((_) {
notifyListeners();
});
}
late final StreamSubscription<dynamic> _subscription;
@override
void notifyListeners() {
super.notifyListeners();
print("refreshing the router");
}
@override
void dispose() {
_subscription.cancel();
super.dispose();
}
}
void main() {
GoRouter.optionURLReflectsImperativeAPIs = true;
WidgetsFlutterBinding.ensureInitialized();
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
final _rootNavigatorKey = GlobalKey<NavigatorState>();
final GoRouter _router = GoRouter(
initialLocation: '/',
navigatorKey: _rootNavigatorKey,
refreshListenable: StreamListener(counterStream.stateStream),
routes: <RouteBase>[
ShellRoute(
builder: (context, state, child) {
return GenericPage(child: child);
},
routes: [
GoRoute(
path: '/',
builder: (BuildContext context, GoRouterState state) =>
const GenericPage(showPushButton: true, path: 'a'),
routes: [
GoRoute(
path: 'a',
name: "a",
builder: (BuildContext context, GoRouterState state) =>
const GenericPage(showPushButton: true, path: 'b'),
routes: [
GoRoute(
path: 'b',
name: 'b',
builder: (BuildContext context, GoRouterState state) =>
const GenericPage(showBackButton: true),
),
],
),
],
),
],
),
],
);
class _MyAppState extends State<MyApp> {
late StreamSubscription<int> _stateSubscription;
int _currentState = 0;
@override
void initState() {
super.initState();
_stateSubscription = counterStream.stateStream.listen((state) {
setState(() {
_currentState = state;
});
});
}
@override
void dispose() {
_stateSubscription.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return MaterialApp.router(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
routerConfig: _router,
);
}
}
class GenericPage extends StatefulWidget {
final Widget? child;
final bool showPushButton;
final bool showBackButton;
final String? path;
const GenericPage({
this.child,
Key? key,
this.showPushButton = false,
this.showBackButton = false,
this.path,
}) : super(key: key ?? const ValueKey<String>('ShellWidget'));
@override
State<GenericPage> createState() => _GenericPageState();
}
class _GenericPageState extends State<GenericPage> {
late StreamSubscription<int> _stateSubscription;
int _currentState = 0;
@override
void initState() {
super.initState();
_stateSubscription = counterStream.stateStream.listen((state) {
setState(() {
_currentState = state;
});
});
}
@override
void dispose() {
_stateSubscription.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: widget.child != null
? AppBar(
title: Text('Count: $_currentState'),
)
: null,
body: _buildWidget(context));
}
Widget _buildWidget(BuildContext context) {
if (widget.child != null) {
return widget.child!;
}
if (widget.showBackButton) {
return TextButton(
onPressed: () {
// WHEN THE USER PRESSES THIS BUTTON, THE URL
// DOESN'T CHANGE, BUT THE SCREEN DOES
counterStream.increment(); // <- when removing this line the issue is gone
GoRouter.of(context).pop();
},
child: Text("<- Go Back"),
);
}
if (widget.showPushButton) {
return TextButton(
onPressed: () {
GoRouter.of(context).goNamed(widget.path!);
},
child: Text("Push ->"),
);
}
return Text('Current state: $_currentState');
}
}Flutter Doctor output
Doctor output
[✓] Flutter (Channel stable, 3.19.6, on macOS 14.5 23F79 darwin-x64, locale en-AU)
• Flutter version 3.19.6 on channel stable at /Applications/flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision 54e66469a9 (8 weeks ago), 2024-04-17 13:08:03 -0700
• Engine revision c4cd48e186
• Dart version 3.3.4
• DevTools version 2.31.1
[✓] Android toolchain - develop for Android devices (Android SDK version 32.1.0-rc1)
• Android SDK at /Users/shady/Library/Android/sdk
• Platform android-33, build-tools 32.1.0-rc1
• Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 11.0.11+0-b60-7590822)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 15.2)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Build 15C500b
• CocoaPods version 1.15.2
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 2021.1)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 11.0.11+0-b60-7590822)
[✓] IntelliJ IDEA Ultimate Edition (version 2024.1.3)
• IntelliJ at /Users/shady/Applications/IntelliJ IDEA Ultimate.app
• Flutter plugin version 80.0.2
• Dart plugin version 241.17890.8
[✓] VS Code (version 1.89.1)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension can be installed from:
🔨 https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter
[✓] VS Code (version 1.86.0-insider)
• VS Code at /Applications/Visual Studio Code - Insiders.app/Contents
• Flutter extension can be installed from:
🔨 https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter
[✓] Connected device (2 available)
• macOS (desktop) • macos • darwin-x64 • macOS 14.5 23F79
darwin-x64
• Chrome (web) • chrome • web-javascript • Google Chrome
125.0.6422.142
[✓] Network resources
• All expected network resources are available.
Metadata
Metadata
Assignees
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work listfound in release: 3.22Found to occur in 3.22Found to occur in 3.22found in release: 3.23Found to occur in 3.23Found to occur in 3.23has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onp: go_routerThe go_router packageThe go_router packagepackageflutter/packages repository. See also p: labels.flutter/packages repository. See also p: labels.platform-webWeb applications specificallyWeb applications specificallyteam-frameworkOwned by Framework teamOwned by Framework teamtriaged-frameworkTriaged by Framework teamTriaged by Framework team