-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[go_router] Adds onException to GoRouter constructor. (#4216)
fixes flutter/flutter#108144
- Loading branch information
Showing
19 changed files
with
420 additions
and
99 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,34 @@ | ||
By default, go_router comes with default error screens for both `MaterialApp` | ||
and `CupertinoApp` as well as a default error screen in the case that none is | ||
used. You can also replace the default error screen by using the | ||
[errorBuilder](https://pub.dev/documentation/go_router/latest/go_router/GoRouter/GoRouter.html) | ||
parameter: | ||
There are several kinds of errors or exceptions in go_router. | ||
|
||
* GoError and AssertionError | ||
|
||
This kind of errors are thrown when go_router is used incorrectly, for example, if the root | ||
[GoRoute.path](https://pub.dev/documentation/go_router/latest/go_router/GoRoute/path.html) does | ||
not start with `/` or a builder in GoRoute is not provided. These errors should not be caught and | ||
must be fixed in code in order to use go_router. | ||
|
||
* GoException | ||
|
||
This kind of exception are thrown when the configuration of go_router cannot handle incoming requests | ||
from users or other part of the code. For example, an GoException is thrown when user enter url that | ||
can't be parsed according to pattern specified in the `GoRouter.routes`. These exceptions can be | ||
handled in various callbacks. | ||
|
||
Once can provide a callback to `GoRouter.onException` to handle this exception. In this callback, | ||
one can choose to ignore, redirect, or push different pages depending on the situation. | ||
See [Exception Handling](https://github.com/flutter/packages/blob/main/packages/go_router/example/lib/exception_handling.dart) | ||
on a runnable example. | ||
|
||
The `GoRouter.errorBuilder` and `GoRouter.errorPageBuilder` can also be used to handle exceptions. | ||
```dart | ||
GoRouter( | ||
/* ... */ | ||
errorBuilder: (context, state) => ErrorScreen(state.error), | ||
); | ||
``` | ||
|
||
By default, go_router comes with default error screens for both `MaterialApp` | ||
and `CupertinoApp` as well as a default error screen in the case that none is | ||
used. | ||
|
||
**Note** the `GoRouter.onException` supersedes other exception handling APIs. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
// Copyright 2013 The Flutter Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
import 'package:flutter/material.dart'; | ||
import 'package:go_router/go_router.dart'; | ||
|
||
/// This sample app shows how to use `GoRouter.onException` to redirect on | ||
/// exception. | ||
/// | ||
/// The first route '/' is mapped to [HomeScreen], and the second route | ||
/// '/404' is mapped to [NotFoundScreen]. | ||
/// | ||
/// Any other unknown route or exception is redirected to `/404`. | ||
void main() => runApp(const MyApp()); | ||
|
||
/// The route configuration. | ||
final GoRouter _router = GoRouter( | ||
onException: (_, GoRouterState state, GoRouter router) { | ||
router.go('/404', extra: state.location); | ||
}, | ||
routes: <RouteBase>[ | ||
GoRoute( | ||
path: '/', | ||
builder: (BuildContext context, GoRouterState state) { | ||
return const HomeScreen(); | ||
}, | ||
), | ||
GoRoute( | ||
path: '/404', | ||
builder: (BuildContext context, GoRouterState state) { | ||
return NotFoundScreen(uri: state.extra as String? ?? ''); | ||
}, | ||
), | ||
], | ||
); | ||
|
||
/// The main app. | ||
class MyApp extends StatelessWidget { | ||
/// Constructs a [MyApp] | ||
const MyApp({super.key}); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return MaterialApp.router( | ||
routerConfig: _router, | ||
); | ||
} | ||
} | ||
|
||
/// The home screen | ||
class HomeScreen extends StatelessWidget { | ||
/// Constructs a [HomeScreen] | ||
const HomeScreen({super.key}); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Scaffold( | ||
appBar: AppBar(title: const Text('Home Screen')), | ||
body: Center( | ||
child: ElevatedButton( | ||
onPressed: () => context.go('/some-unknown-route'), | ||
child: const Text('Simulates user entering unknown url'), | ||
), | ||
), | ||
); | ||
} | ||
} | ||
|
||
/// The not found screen | ||
class NotFoundScreen extends StatelessWidget { | ||
/// Constructs a [HomeScreen] | ||
const NotFoundScreen({super.key, required this.uri}); | ||
|
||
/// The uri that can not be found. | ||
final String uri; | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Scaffold( | ||
appBar: AppBar(title: const Text('Page Not Found')), | ||
body: Center( | ||
child: Text("Can't find a page for: $uri"), | ||
), | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 18 additions & 0 deletions
18
packages/go_router/example/test/exception_handling_test.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// Copyright 2013 The Flutter Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
import 'package:flutter_test/flutter_test.dart'; | ||
import 'package:go_router_examples/exception_handling.dart' as example; | ||
|
||
void main() { | ||
testWidgets('example works', (WidgetTester tester) async { | ||
await tester.pumpWidget(const example.MyApp()); | ||
expect(find.text('Simulates user entering unknown url'), findsOneWidget); | ||
|
||
await tester.tap(find.text('Simulates user entering unknown url')); | ||
await tester.pumpAndSettle(); | ||
expect(find.text("Can't find a page for: /some-unknown-route"), | ||
findsOneWidget); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.