Go Router + Riverpod Tutorial 2: Conditional Redirection with Guards

Search for a command to run...

No comments yet. Be the first to comment.
In here we'll look at a series of tutorials covering Go Router and Riverpod together.
First let's create the required screens. Settings Page: Settings page has two buttons: (Go to Account Settings, Logout). class SettingsPage extends ConsumerWidget { const SettingsPage({super.key}); @override Widget build(BuildContext context, ...
While I generally write about Flutter. This problem has been bugging me for a while and there seem to be limited resources to find a solution. So for anyone who is looking for a solution. Here you go: Type edge:flags into the address bar and open it...
In this tutorial, we’ll go through covering interceptor, which is a very crucial feature of Dio. You can find the entire source code for the project here: dio_tasker Understanding Interceptors: What is an interceptor? An interceptor in Dio is a powe...

In this part, we’ll enhance our Task Manager app by parsing JSON responses and handling different types of errors. We’ll use Dio’s built-in error handling mechanisms. You can find the source code of the entire app here: dio_tasker Parsing JSON Respon...

While building apps in Flutter is extremely fluid and wonderfully intuitive. We obviously know that we can’t build the next TikTok or Twitter by only building offline apps. Which is why we absolutely need internet capabilities in our Flutter apps. Th...

Understanding when to use setState in Flutter is crucial for managing our app’s state effectively. Here’s a detailed guide: When to use setState ? Updating the UI: Use setState when we need to update the UI in response to changes in the internal sta...

In our previous article we have covered basic redirect. Now let's take a look at Conditional Redirection.
Guards: Guards are essentially functions that you can define to determine whether a particular redirection should happen or not.
They evaluate specific conditions (like user authentication status, user roles, or data availability) and return a new route if the conditions are met,
If returned null they proceed with the default route.
First let's define two additional pages:
class ProfilePage extends ConsumerWidget {
const ProfilePage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
appBar: AppBar(
title: const Text('Profile'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'Profile Page', style: TextStyle(fontSize: 24),
),
const SizedBox(height: 10),
ElevatedButton(
onPressed: () {
ref.read(authProvider.notifier).logout();
},
child: const Text('Logout'),
),
],
),
),
);
}
}
class AdminPage extends ConsumerWidget {
const AdminPage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
appBar: AppBar(
title: const Text('Admin'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'Admin Page',
style: TextStyle(fontSize: 24),
),
const SizedBox(height: 10),
ElevatedButton(
onPressed: () {
ref.read(authProvider.notifier).logout();
},
child: const Text('Logout'),
),
],
),
),
);
}
}
Now that we have the Admin Page and Profile Page. Let's see how to connect all the pages to app_router.dart
Let's add a guard to both profile page and admin page.
final routerProvider = Provider<GoRouter>((ref) {
return GoRouter(
initialLocation: '/home',
routes: [
GoRoute(path: '/home', builder: (context, state) => const HomePage()),
GoRoute(path: '/login', builder: (context, state) => const LoginPage()),
GoRoute(path: '/profile', builder: (context, state) => const ProfilePage(),
redirect: (context, state) {
// GUARD ADDED FOR PAGE. CAN GO TO THIS PAGE ONLY WHEN LOGGED IN
final loggedIn = ref.watch(authProvider);
if (!loggedIn) {
return '/login';
}
return null;
},
),
GoRoute(path: '/admin', builder: (context, state) => const AdminPage(),
redirect: (context, state) {
// GUARD ADDED FOR PAGE. CAN GO TO THIS PAGE ONLY WHEN LOGGED IN
final loggedIn = ref.watch(authProvider);
if (!loggedIn) {
return '/login';
}
return null;
},
),
],
redirect: (context, state) {
final loggedIn = ref.watch(authProvider);
final isLoggingIn = state.path == '/login';
if (!loggedIn && !isLoggingIn) {
return '/login';
} else if(loggedIn && isLoggingIn) {
return '/home';
}
return null;
});
});
Now the end goal is that we can only go to the profile page as well as admin page only when logged in

Perfect. As of now we are doing with Basic Redirection, Redirection using guards. We still have 3 tutorials where we discuss advanced concepts of Redirection using Riverpod. So keep tuned for more.