Skip to content

Commit

Permalink
[go_router] add current state getter (#7651)
Browse files Browse the repository at this point in the history
Adds a current state getter that returns `GoRouterState`.

I've no idea if this is correct but the added tests seem to be passing. Rebuilding the state may be expensive too ?

Fix: flutter/flutter#129833 
fixes flutter/flutter#148215
  • Loading branch information
cedvdb authored Nov 4, 2024
1 parent 6276210 commit da4c3ee
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 2 deletions.
6 changes: 5 additions & 1 deletion packages/go_router/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
## 14.4.0

- Adds current state getter on `GoRouter` that returns the current `GoRouterState`.

## 14.3.0

- Added missing implementation for the routerNeglect parameter in GoRouter.
- Adds missing implementation for the routerNeglect parameter in GoRouter.

## 14.2.9

Expand Down
6 changes: 6 additions & 0 deletions packages/go_router/lib/src/delegate.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import 'configuration.dart';
import 'match.dart';
import 'misc/errors.dart';
import 'route.dart';
import 'state.dart';

/// GoRouter implementation of [RouterDelegate].
class GoRouterDelegate extends RouterDelegate<RouteMatchList>
Expand Down Expand Up @@ -169,6 +170,11 @@ class GoRouterDelegate extends RouterDelegate<RouteMatchList>
}());
}

/// The top [GoRouterState], the state of the route that was
/// last used in either [GoRouter.go] or [GoRouter.push].
GoRouterState? get state => currentConfiguration.last
.buildState(_configuration, currentConfiguration);

/// For use by the Router architecture as part of the RouterDelegate.
GlobalKey<NavigatorState> get navigatorKey => _configuration.navigatorKey;

Expand Down
8 changes: 8 additions & 0 deletions packages/go_router/lib/src/router.dart
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,14 @@ class GoRouter implements RouterConfig<RouteMatchList> {
}());
}

/// The top [GoRouterState], the state of the route that was
/// last used in either [GoRouter.go] or [GoRouter.push].
///
/// Accessing this property via GoRouter.of(context).state will not
/// cause rebuild if the state has changed, consider using
/// GoRouterState.of(context) instead.
GoRouterState? get state => routerDelegate.state;

/// Whether the imperative API affects browser URL bar.
///
/// The Imperative APIs refer to [push], [pushReplacement], or [replace].
Expand Down
2 changes: 1 addition & 1 deletion packages/go_router/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -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: 14.3.0
version: 14.4.0
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

Expand Down
72 changes: 72 additions & 0 deletions packages/go_router/test/go_router_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5474,6 +5474,78 @@ void main() {
);
});

testWidgets(
'should return the current GoRouterState when router.currentState is called',
(WidgetTester tester) async {
final List<RouteBase> routes = <RouteBase>[
GoRoute(
name: 'home',
path: '/',
builder: (BuildContext context, GoRouterState state) =>
const HomeScreen()),
GoRoute(
name: 'books',
path: '/books',
builder: (BuildContext context, GoRouterState state) =>
const Text('books')),
GoRoute(
name: 'boats',
path: '/boats',
builder: (BuildContext context, GoRouterState state) =>
const Text('boats')),
ShellRoute(
builder: (BuildContext context, GoRouterState state, Widget child) =>
child,
routes: <RouteBase>[
GoRoute(
name: 'tulips',
path: '/tulips',
builder: (BuildContext context, GoRouterState state) =>
const Text('tulips'),
),
],
)
];

final GoRouter router = await createRouter(routes, tester);
await tester.pumpAndSettle();

GoRouterState? state = router.state;
expect(state?.name, 'home');
expect(state?.fullPath, '/');

router.go('/books');
await tester.pumpAndSettle();
state = router.state;
expect(state?.name, 'books');
expect(state?.fullPath, '/books');

router.push('/boats');
await tester.pumpAndSettle();
state = router.state;
expect(state?.name, 'boats');
expect(state?.fullPath, '/boats');

router.pop();
await tester.pumpAndSettle();
state = router.state;
expect(state?.name, 'books');
expect(state?.fullPath, '/books');

router.go('/tulips');
await tester.pumpAndSettle();
state = router.state;
expect(state?.name, 'tulips');
expect(state?.fullPath, '/tulips');

router.go('/books');
router.push('/tulips');
await tester.pumpAndSettle();
state = router.state;
expect(state?.name, 'tulips');
expect(state?.fullPath, '/tulips');
});

testWidgets('should allow route paths without leading /',
(WidgetTester tester) async {
final List<GoRoute> routes = <GoRoute>[
Expand Down

0 comments on commit da4c3ee

Please sign in to comment.