Current field guide · 2026
go, push, and the way back
Use go for a destination described by your route tree; use push when you deliberately want another page on the current stack.
On this page
Pick the user intention first
Changing a primary destination, opening a detail above the current screen, and replacing a transient screen are different actions. Choose an operation for the expected Back behavior, rather than selecting the shortest method name.
Destination navigation
context.go() navigates to the location and builds the corresponding route configuration. It is useful when the location itself should define the resulting page hierarchy. context.push() adds a location above the current stack and can return a result when that page is popped.
Browser history is a separate test
Do not assume imperative page pushes create the same web history as links or destination navigation. Test browser Back, Forward, a pasted link, and a fresh reload on the exact package version you ship. Extra data that exists only in memory is not a durable replacement for a URL.
Returning a result
Await the pushed route only when your flow really needs a result. After asynchronous work, check that the widget context is still mounted before using it. For navigation that should be discoverable as a real link, consider the Link widget from url_launcher alongside your route configuration.
// Change the destination.
context.go('/books/42');
// Open another page and await its result.
final saved = await context.push<bool>('/books/42/edit');
if (!context.mounted) return;
// From the editor:
context.pop(true);Sources & version context
GoRouter.dev documentation edition. Examples illustrate the APIs described in the linked primary documentation. Adapt application-owned widgets and services to your project. They are not an executed Flutter session in this browser.
Run a real stack test: go replaces the location; push adds a page
The difference is observable in the existing starter, rather than inferred from the JavaScript Route Atlas model. This example pins go_router 18.1.1 with the already available Flutter SDK. It tests the widget navigation stack, not the browser’s Back/Forward implementation.
- Use the starter linked on Getting started. Keep its lockfile. Add the complete test below as
test/navigation_stack_test.dart; it is an additional test, not a claim that the older ZIP already contains this file. - Run
flutter analyze --no-pubandflutter test --no-pub --reporter expandedafter resolving the pinned dependencies. - Run
flutter build web --release --csp --no-web-resources-cdn --no-wasm-dry-run --no-pub. Check navigation in the resulting application separately before relying on browser history behaviour.
Observed on 28 October 2026: analysis found no issues; all five tests passed, including the added stack test; the release Web build completed. The test goes directly to Book 42 with the notes tab and observes canPop == false. Starting from Home and pushing that same location observes canPop == true; pop returns Home without an exception.
Complete executed test
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:gorouter_starter/main.dart';
void main() {
testWidgets('go selects a top-level stack; push retains Home', (
tester,
) async {
final router = createRouter();
addTearDown(router.dispose);
await tester.pumpWidget(MaterialApp.router(routerConfig: router));
await tester.pumpAndSettle();
router.go('/books/42?tab=notes');
await tester.pumpAndSettle();
expect(find.text('Book 42'), findsOneWidget);
expect(find.text('Tab: notes'), findsOneWidget);
expect(router.canPop(), isFalse);
router.go('/');
await tester.pumpAndSettle();
router.push('/books/42?tab=notes');
await tester.pumpAndSettle();
expect(find.text('Book 42'), findsOneWidget);
expect(router.canPop(), isTrue);
router.pop();
await tester.pumpAndSettle();
expect(find.text('GoRouter starter'), findsOneWidget);
expect(tester.takeException(), isNull);
});
}
These results establish the tested starter’s stack and compilation on the recorded SDK. They do not prove every navigation pattern, an unpinned future version, or real browser Back/Forward across external pages. Keep the distinction between route matching, widget stack and browser history in your own regression record.
Source: pub.dev.