[go_router] Allow any number of the same page on the stack (#2339)
diff --git a/packages/go_router/CHANGELOG.md b/packages/go_router/CHANGELOG.md
index 2ddd57a..465df98 100644
--- a/packages/go_router/CHANGELOG.md
+++ b/packages/go_router/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 4.2.3
+
+- Fixes a bug where the ValueKey to be the same when a page was pushed multiple times.
+
## 4.2.2
- Fixes a bug where go_router_builder wasn't detecting annotations.
diff --git a/packages/go_router/lib/src/delegate.dart b/packages/go_router/lib/src/delegate.dart
index 1af969c..29f0f25 100644
--- a/packages/go_router/lib/src/delegate.dart
+++ b/packages/go_router/lib/src/delegate.dart
@@ -45,10 +45,27 @@
final GlobalKey<NavigatorState> _key = GlobalKey<NavigatorState>();
RouteMatchList _matches = RouteMatchList.empty();
+ final Map<String, int> _pushCounts = <String, int>{};
- /// Push the given location onto the page stack
+ /// Pushes the given location onto the page stack
void push(RouteMatch match) {
- _matches.push(match);
+ // Remap the pageKey to allow any number of the same page on the stack
+ final String fullPath = match.fullpath;
+ final int count = (_pushCounts[fullPath] ?? 0) + 1;
+ _pushCounts[fullPath] = count;
+ final ValueKey<String> pageKey = ValueKey<String>('$fullPath-p$count');
+ final RouteMatch newPageKeyMatch = RouteMatch(
+ route: match.route,
+ subloc: match.subloc,
+ fullpath: match.fullpath,
+ encodedParams: match.encodedParams,
+ queryParams: match.queryParams,
+ extra: match.extra,
+ error: match.error,
+ pageKey: pageKey,
+ );
+
+ _matches.push(newPageKeyMatch);
notifyListeners();
}
diff --git a/packages/go_router/pubspec.yaml b/packages/go_router/pubspec.yaml
index 4c8da3d..0b2d6f0 100644
--- a/packages/go_router/pubspec.yaml
+++ b/packages/go_router/pubspec.yaml
@@ -1,7 +1,7 @@
name: go_router
description: A declarative router for Flutter based on Navigation 2 supporting
deep linking, data-driven routes and more
-version: 4.2.2
+version: 4.2.3
repository: https://github.com/flutter/packages/tree/main/packages/go_router
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+go_router%22
diff --git a/packages/go_router/test/delegate_test.dart b/packages/go_router/test/delegate_test.dart
index a85d536..b4a4173 100644
--- a/packages/go_router/test/delegate_test.dart
+++ b/packages/go_router/test/delegate_test.dart
@@ -16,6 +16,7 @@
initialLocation: '/',
routes: <GoRoute>[
GoRoute(path: '/', builder: (_, __) => const DummyStatefulWidget()),
+ GoRoute(path: '/a', builder: (_, __) => const DummyStatefulWidget()),
GoRoute(
path: '/error',
builder: (_, __) => const ErrorScreen(null),
@@ -56,6 +57,38 @@
});
});
+ group('push', () {
+ testWidgets(
+ 'It should return different pageKey when push is called',
+ (WidgetTester tester) async {
+ final GoRouter goRouter = await createGoRouter(tester);
+ expect(goRouter.routerDelegate.matches.matches.length, 1);
+ expect(
+ goRouter.routerDelegate.matches.matches[0].pageKey,
+ null,
+ );
+
+ goRouter.push('/a');
+ await tester.pumpAndSettle();
+
+ expect(goRouter.routerDelegate.matches.matches.length, 2);
+ expect(
+ goRouter.routerDelegate.matches.matches[1].pageKey,
+ const Key('/a-p1'),
+ );
+
+ goRouter.push('/a');
+ await tester.pumpAndSettle();
+
+ expect(goRouter.routerDelegate.matches.matches.length, 3);
+ expect(
+ goRouter.routerDelegate.matches.matches[2].pageKey,
+ const Key('/a-p2'),
+ );
+ },
+ );
+ });
+
group('canPop', () {
testWidgets(
'It should return false if there is only 1 match in the stack',