0

I am using the ScopedModel pattern, but I am also interested how this same problem is addressed in the similar Provider pattern.

Currently I have a ScopedModel with a bool exposed called loggedIn. When the FirebaseonAuthStateChanged stream changes user log in state, my ScopedModel changes that bool, and calls NotifyListeners. All straight forward stuff.

Now I am confused as to the best way to push or pop routes based on this ScopedModel.

Should all my logged in screens (screens that require a user) have the following code in build method?

WidgetsBinding.instance.addPostFrameCallback((_) {
  if (!auth.hasUser)
    Navigator.of(context).pushNamedAndRemoveUntil('/entry', (Route<dynamic> route) => });
});

That seems a little excessive to have this code on every single screen. Is there a way I can define this log screen change behaviour somewhere only once?

Scorb
  • 1,654
  • 13
  • 70
  • 144

1 Answers1

0

create a Widget for it ;)


class Validation extends StatefulWidget {
  final Function validator;
  final Widget child;

  const Validation({Key key, this.validator, this.child}) : super(key: key);
  @override
  _ValidationState createState() => _ValidationState();
}

class _ValidationState extends State<Validation> {
  @override
  void initState() {
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) { 
      widget.validator();
    });
    super.initState();
  }
  
  @override
  Widget build(BuildContext context) {
    return widget.child;
  }
}

now use it everywhere

  @override
  Widget build(BuildContext context) {
    return Validation(
      validator: (){
        if (!auth.hasUser){
          Navigator.of(context).pushNamedAndRemoveUntil('/entry', (Route<dynamic> route) => false);
        }          
      },
      child: MyAwesomePage(),
    );
  }

you can further simplify if the validation is same everywhere or create multiple validation widget according to the validations required,

FOR YOUR CASE



class LoginValidation extends StatefulWidget {
  final String routeIfNotLoggedIn;
  final Widget child;

  const LoginValidation({Key key, this.routeIfNotLoggedIn, this.child}) : super(key: key);
  @override
  _LoginValidationState createState() => _LoginValidationState();
}

class _LoginValidationState extends State<LoginValidation> {
  @override
  void initState() {
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      if (!auth.hasUser){
        Navigator.of(context).pushNamedAndRemoveUntil(widget.routeIfNotLoggedIn, (Route<dynamic> route) => false);
      }
    });
    super.initState();
  }
}

and use it


  @override
  Widget build(BuildContext context) {
    return LoginValidation(
      routeIfNotLoggedIn: "/myLoginRoute",
      child: MyAwesomePage(),
    );
  }
Yadu
  • 2,979
  • 2
  • 12
  • 27