# Navigation

To navigate between pages, use the `GoRouter.go` method:

```dart
// navigate using the GoRouter
onTap: () => GoRouter.of(context).go('/page2')
```

go_router also provides a simplified means of navigation using Dart extension
methods:

```dart
// navigate using the GoRouter more easily
onTap: () => context.go('/page2')
```

The simplified version maps directly to the more fully-specified version, so you
can use either. If you're curious, the ability to just call `context.go(...)`
and have magic happen is where the name of go_router came from.

If you'd like to navigate via [the `Link`
widget](https://pub.dev/documentation/url_launcher/latest/link/link-library.html),
that works, too:

```dart
Link(
  uri: Uri.parse('/page2'),
  builder: (context, followLink) => TextButton(
    onPressed: followLink,
    child: const Text('Go to page 2'),
  ),
),
```

If the `Link` widget is given a URL with a scheme, e.g. `https://flutter.dev`,
then it will launch the link in a browser. Otherwise, it'll navigate to the link
inside the app using the built-in navigation system.

You can also navigate to a [named route](/named-routes).

## Pushing pages

In addition to the `go` method, go_router also provides a `push` method. Both
`go` and `push` can be used to build up a stack of pages, but in different ways.
The `go` method does this by turning a single location into any number of pages
in a stack using [sub-routes](/sub-routes).

The `push` method is used to push a single page onto the stack of existing
pages, which means that you can build up the stack programmatically instead of
declaratively. When the `push` method matches an entire stack via sub-routes, it
will take the top-most page from the stack and push that page onto the stack.

You can also push a [named route](/named-routes).

## Popping pages

If you'd like to pop a page from the go_router stack, you can use the `pop`
method.

## Initial Location

If you'd like to set an initial location for routing, you can set the
`initialLocation` argument of the `GoRouter` constructor:

```dart
final _router = GoRouter(
  routes: ...,
  initialLocation: '/page2',
);
```

The value you provide to `initialLocation` will be ignored if your app is
started using [deep linking](/declarative-routing#deep-linking).

## Current location

If you want to know the current location, use the `GoRouter.location` property.

If you'd like to know when the current location changes, either because of
manual navigation or a deep link or a pop due to the user pushing the Back
button, the `GoRouter` is a
[`ChangeNotifier`](https://api.flutter.dev/flutter/foundation/ChangeNotifier-class.html),
which means that you can call `addListener` to be notified when the location
changes, either manually or via Flutter's builder widget for `ChangeNotifier`
objects, the non-intuitively named
[`AnimatedBuilder`](https://stackoverflow.com/a/67016227):

```dart
class RouterLocationView extends StatelessWidget {
  const RouterLocationView({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final router = GoRouter.of(context);
    return AnimatedBuilder(
      animation: router,
      builder: (context, child) => Text(router.location),
    );
  }
}
```

Or, if you're using [the provider package](https://pub.dev/packages/provider),
it comes with built-in support for re-building a `Widget` when a
`ChangeNotifier` changes with a type that is much more clearly suited for the
purpose.
