Redirects
GoRouter Modular delegates redirects to GoRouter. You can define global redirects (in configure) and per-route redirects (in ChildRoute/ModuleRoute), exactly like in GoRouter.
Global redirect (in configure)
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Modular.configure(
appModule: AppModule(),
initialRoute: '/',
// Global GoRouter redirect: decide destination dynamically
redirect: (context, state) {
final loggedIn = auth.isLoggedIn; // your app state
if (!loggedIn) return '/login';
return null; // no redirect
},
);
runApp(AppWidget());
}- Runs on every navigation.
- Return
nullto proceed normally, or a string path to redirect.
Per-route redirect (ChildRoute)
class AppModule extends Module {
@override
List<ModularRoute> get routes => [
ChildRoute(
'/',
child: (context, state) => const HomePage(),
),
ChildRoute(
'/login',
child: (context, state) => const LoginPage(),
// route-level redirect: uses the same GoRouter API
redirect: (context, state) {
final loggedIn = auth.isLoggedIn;
return loggedIn ? '/' : null;
},
),
];
}- The
redirectinChildRouteruns before the page builder. - Useful for simple guards (e.g., login).
Redirect with path parameters
ChildRoute(
'/users/:id',
child: (context, state) => UserPage(id: state.pathParameters['id']!),
redirect: (context, state) {
final id = state.pathParameters['id'];
if (id == null || id.isEmpty) return '/users';
return null;
},
)Best practices
- Prefer a global
redirectfor cross-cutting rules (auth, onboarding). - Prefer per-route
redirectfor local validations. - Avoid loops: ensure the redirect target does not redirect back.
- Redirect to full paths (e.g.,
/login, not relative paths).
For more details, see the official GoRouter redirect documentation.