Historical source · 2021–2022
Original guide · Navigator Integration
Preserved original documentation, with its original version context.
On this page
Navigator Integration
If you'd like to integrate with the built in Navigator widget, you can, as shown in this snippet from the navigator integration example:
Future<void> _addPerson(BuildContext context) async {
final person = await Navigator.push<Person>(
context,
MaterialPageRoute(
builder: (context) => NewPersonScreen(family: widget.family),
),
);
if (person != null) {
setState(() => widget.family.people.add(person));
context.goNamed('person', params: {
'fid': widget.family.id,
'pid': person.id,
});
}
}This example shows how to use the Navigator widget to push a new page and gather the result. It doesn't use the GoRouter but works just the way you'd expect, e.g. it will create a new page on the stack of pages, show a Back button in the AppBar, etc. To return results, use Navigator.pop as you normally would:
ButtonBar(children: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('Cancel'),
),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
final person = Person(
id: 'p${widget.family.people.length + 1}',
name: _nameController.text,
age: int.parse(_ageController.text),
);
Navigator.pop(context, person);
}
},
child: const Text('Create'),
),
]),You can feel free to use GoRouter and Navigator together like this. However, one thing that using Navigator.push in this way will not do is update the browser's address bar. If you want that, you'll need to use GoRouter.go or GoRouter.push. You'll notice, however, that neither go nor push provides for waiting on results. That's because GoRouter is meant for use with deep and dynamic linking, i.e. everything about a location in your app can be expressed as a link. If you're calling Navigator.push and waiting on the results from some random place in your app, that's not something that can be represented in a link.
However, that doesn't mean that you can't use GoRouter to navigate to a page that gathers user input; in fact, that's a common scenario that GoRouter supports. Because the results of the navigation are not available to the caller when using the GoRouter, the screen itself would be responsible for managing what happens to the user input, e.g.
ButtonBar(children: [
TextButton(
onPressed: () =>
// Navigator.pop(context) would work here, too
context.goNamed('family', params: {'fid': widget.family.id}),
child: const Text('Cancel'),
),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
final person = Person(
id: 'p${widget.family.people.length + 1}',
name: _nameController.text,
age: int.parse(_ageController.text),
);
widget.family.people.add(person);
context.goNamed('person', params: {
'fid': widget.family.id,
'pid': person.id,
});
}
},
child: const Text('Create'),
),
]),With this implementation, you can set up a sub-route to provide a page to add a new person:
GoRoute(
name: 'home',
path: '/',
builder: ...,
routes: [
GoRoute(
name: 'family',
path: 'family/:fid',
builder: ...,
routes: [
GoRoute(
name: 'person',
path: 'person/:pid',
builder: ...,
),
GoRoute(
name: 'new-person',
path: 'new-person',
builder: (context, state) {
final family = Families.family(state.params['fid']!);
return NewPersonScreen(family: family);
},
),
],
),
],
),And now your _addPerson method would look like this:
void _addPerson(BuildContext context) {
context.goNamed('new-person', params: {'fid': widget.family.id});
}And finally, when you're making changes to the data in your app that appears in more than one place, e.g. updating the list of Person objects in a Family on one page while also showing a list of those Person objects on another page, you'll want to ensure that the widgets in your app can be rebuilt when the state they depend on changes. For this, I recommend a state management solution like provider.
There's no reason not to use the Navigator in your app when you're using the GoRouter, but you'll want to be careful how you manage your app's state and the implications of using Navigator vs. GoRouter for navigation.
Sources & version context
GoRouter.dev documentation edition. The preserved text describes the original package APIs. Follow the current guide before using it in a new project.