Problem: My app always displays the login screen regardless of whatever kind of navigation I make (like setting the initial location to another page, context.push, context.go, etc). I have implemented a redirecting function in the authentication system that redirects user back to the login page if they are unauthenticated but that does not seem to be the culprit (the two print statements: “authState changes” and “Redirect!” did not get called when I pressed the navigating button).
My main.dart file:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:sneaker_app/models/cart.dart';
import 'package:sneaker_app/routes/app_route_config.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:sneaker_app/services/auth_service.dart';
import 'firebase_options.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
// Referesh GoRouter configuration every time authState changes (Authentication guaranteed)
FirebaseAuth.instance.authStateChanges().listen((User? user) {
print("authState changes");
MyAppRouter.router.refresh();
});
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<Cart>(create: (context) => Cart()),
ChangeNotifierProvider<AuthService>(
create: (context) => AuthService())
],
child: MaterialApp.router(
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.grey)),
routerConfig: MyAppRouter.router,
));
}
}
My App router configs:
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart';
import 'package:sneaker_app/models/shopee_tile.dart';
import 'package:sneaker_app/pages/home_page.dart';
import 'package:sneaker_app/pages/item_page.dart';
import 'package:sneaker_app/pages/login_page.dart';
import 'package:sneaker_app/pages/signup_page.dart';
import 'package:sneaker_app/routes/app_route_constants.dart';
import 'package:sneaker_app/services/auth_service.dart';
class MyAppRouter {
static final GoRouter router = GoRouter(
initialLocation: "/login",
routes: [
GoRoute(
name: MyAppRouteConstants.homeRouteName,
path: "/",
builder: (context, state) => HomePage()),
GoRoute(
name: MyAppRouteConstants.itemRouteName,
path: "/item/:id",
builder: (context, state) {
ShopeeTile item = state.extra as ShopeeTile;
return ItemPage(
id: int.parse(state.pathParameters["id"]!),
item: item,
);
}),
GoRoute(
name: MyAppRouteConstants.loginRouteName,
path: "/login",
builder: (context, state) => LoginPage()),
GoRoute(
name: MyAppRouteConstants.signupRouteName,
path: "/signup",
builder: (context, state) => SignupPage()),
],
redirect: (BuildContext context, GoRouterState state) async {
final bool loggedIn =
Provider.of<AuthService>(context, listen: false).user != null;
final bool loggingIn = state.matchedLocation == "/login";
print("Redirect!");
if (!loggedIn) return "/login";
if (loggingIn) return "/";
// no need to redirect at all
return null;
},
);
}
I can ensure that the constants in MyAppRouteConstants match their path
Here is the button widget on the login page
TextButton(
child: Text('Sign up'),
onPressed: () {
context.pushNamed(MyAppRouteConstants.signupRouteName);
},
),
I tried to debug the problem by putting print statements but I couldn’t find out why the app only stuck to the login page and did not navigate at all.