Table of Contents
- Learn go_router in Flutter (Modern Declarative Routing)
Learn go_router in Flutter (Modern Declarative Routing) #
go_router is a high-level routing package built on Navigator 2.0 that simplifies navigation, deep linking, and URL-based routing. It removes boilerplate while keeping navigation declarative and scalable.
It is the recommended routing solution by the Flutter team for most apps.
Why go_router? #
- Simple API over Navigator 2.0
- Built-in deep linking
- URL-based navigation
- Works perfectly with Flutter Web
- Cleaner than Navigator 1.0 & 2.0
Install Package go_router #
dependencies: go_router: ^14.0.0
Basic Setup go_router #
Define Routes #
final GoRouter router = GoRouter(
initialLocation: '/',
routes: [
GoRoute(
path: '/',
builder: (context, state) => HomeScreen(),
),
GoRoute(
path: '/profile',
builder: (context, state) => ProfileScreen(),
),
],
);
Use MaterialApp.router #
MaterialApp.router( routerConfig: router, );
Navigation Methods #
1. Go to a Route (Replace) #
context.go('/profile');
2. Push a Route (Keep Stack) #
context.push('/profile');
3. Go Back #
context.pop();
Passing Data #
1. Path Parameters #
GoRoute(
path: '/user/:id',
builder: (context, state) {
final id = state.pathParameters['id']!;
return UserScreen(id: id);
},
);
Navigate:
context.go('/user/10');
2. Query Parameters #
context.go('/search?query=flutter&page=1');
final query = state.uri.queryParameters['query'];
3. Extra Data (Objects) #
context.go( '/details', extra: Product(id: 1, name: 'Laptop'), );
final product = state.extra as Product;
Named Routes (Recommended) #
GoRoute( name: 'profile', path: '/profile', builder: (context, state) => ProfileScreen(), );
Navigate:
context.goNamed('profile');
Nested Navigation #
GoRoute(
path: '/dashboard',
builder: (context, state) => DashboardScreen(),
routes: [
GoRoute(
path: 'settings',
builder: (context, state) => SettingsScreen(),
),
],
);
URL:
/dashboard/settings
Authentication Guard (Redirect) #
final router = GoRouter(
redirect: (context, state) {
final isLoggedIn = false;
if (!isLoggedIn && state.location != '/login') {
return '/login';
}
return null;
},
routes: [
GoRoute(
path: '/login',
builder: (_, __) => LoginScreen(),
),
GoRoute(
path: '/',
builder: (_, __) => HomeScreen(),
),
],
);
Error Handling #
errorBuilder: (context, state) => NotFoundScreen(),
ShellRoute (Bottom Navigation) #
ShellRoute(
builder: (context, state, child) {
return Scaffold(
bottomNavigationBar: BottomNav(),
body: child,
);
},
routes: [
GoRoute(
path: '/home',
builder: (_, __) => HomeScreen(),
),
GoRoute(
path: '/profile',
builder: (_, __) => ProfileScreen(),
),
],
);
go_router vs Navigator #
| Feature | go_router | Navigator 1.0 |
|---|---|---|
| Declarative | Yes | No |
| Deep Linking | Yes | Limited |
| Web Support | Excellent | Weak |
| Boilerplate | Low | Low |
| Scalability | High | Medium |
Best Practices #
- Prefer named routes
- Use redirect for auth & role checks
- Use ShellRoute for bottom navigation
- Avoid passing heavy objects via
extra - Combine with Provider / Riverpod / Bloc
When to Use go_router #
Use go_router when:
- Building Flutter Web
- App needs deep linking
- Medium to large apps
- Clean routing architecture
Avoid when:
- Very small apps
- You only need 2–3 screens
Summary #
go_router is the best balance between power and simplicity.
It brings Navigator 2.0 features without complexity and is production-ready.