0

I have a big problem using state management with Providers and the navigator.

Things that we must know:

1) My RESTFUL API gives a token that expires on 12h.

2) My home: parameter is conditioned if the user is authenticated or nor.. if not, based in other parameters I must decide what screen must be the home.

3) If I'm on one screen and the token gets expired on ANY request that the app is doing to the API I:

  • Call a function inside my auth provider that do logout procedures, (i clean the localStorage with the token). This auth provider sets a property called isAuth to false.
  • When isAuth is false, if you look the main.dart file at home: you will see that will show the LoginPage().

Everything here is good. The problem is when i must do a redirect using the Navigator.of..... If, for example, in case of error of token expired I do: Navigator.popUntil(context, ModalRoute.withName('/login')); the app goes to the LoginPage() without problem, but... when I try to use the login (using the login function of auth provider) it's stay on the login page! If I use in any place the Navigator to go to any other place, it's appears to override the 'state management way' that I use to control which page shows as home.

Can you help me please?

My main.dart code:

// Providers
import 'package:provider/provider.dart';
import 'package:cadsanjuan_movil/providers/auth.dart';

// Pages
import './pages/login_page.dart';
import './pages/initial_loading_page.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  final storage = new FlutterSecureStorage();
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
        providers: [
          ChangeNotifierProvider<Auth>(create: (context) => Auth()),
          ChangeNotifierProvider<TurnActive>(create: (context) => TurnActive()),
          ChangeNotifierProxyProvider<TurnActive, Checkup>(
              create: (context) => Checkup(),
              update: (_, turnActive, checkup) {
                checkup.turnData = turnActive.turnData;
                return checkup;
              }),
          ChangeNotifierProxyProvider<Auth, ErrorProvider>(
              create: (context) => ErrorProvider(),
              update: (_, auth, errorProvider) {
                errorProvider.logoff = auth.logoff;
                return errorProvider;
              }),
        ],
        child: Consumer3<Auth, TurnActive, Checkup>(
          builder: (context, auth, turnActive, checkup, _) {
            return MaterialApp(
              title: 'CAD App',
              theme: ThemeData(
                primarySwatch: Colors.blue,
              ),
              home: auth.isAuth
                  ? (turnActive.turnData != null &&
                          turnActive.turnData['turn']['checkUpStartId'] != null)
                      ? CheckupPage() // Si el cotejo está en proceso
                      : InitialLoadingPage() // Si no hay cotejo iniciado
                  : FutureBuilder(
                      // Si estamos no hay autenticación en el estado, se chequea en el localStorage
                      future: auth.tryAutoLogin(),
                      builder: (ctx, authResultSnapshot) =>
                          authResultSnapshot.connectionState ==
                                  ConnectionState.waiting
                              ? LoadingData()
                              : LoginPage(),
                    ),
              routes: {
                LoginPage.routeName: (context) => LoginPage(),
                InitialLoadingPage.routeName: (context) => InitialLoadingPage(),
                CheckupPage.routeName: (context) => CheckupPage(),
                CheckupGroupsPage.routeName: (context) => CheckupGroupsPage(),
              },
            );
          },
        ));
  }
}
Ali Briceño
  • 1,096
  • 2
  • 17
  • 44

1 Answers1

0

The problem was in this:

Navigator.popUntil(context, ModalRoute.withName('/login'))

If we push the "/login" this override the home parameter in MaterialApp, loads the login page but the page will don't pop because the route. The correct way to do it is:

Navigator.of(context)
          .pushNamedAndRemoveUntil('/', (Route<dynamic> route) => false);

With this one we redirect to '/' and then the state management using home parameter will work.

Ali Briceño
  • 1,096
  • 2
  • 17
  • 44