I am refactoring my Flutter application code by adding Provider as a state management.
Desired behavior: When Home screen opens, app should check if users email verified, if it's not then should show dialog popup.
Problem: It worked fine when I was passing data for EmailVerified through the constructor, but if I want to use Provider, I can't get this data at initState()
lifecycle.
Can you please recommend me correct approach for such use case?
import 'package:myapp/services/authentication.dart';
import 'package:myapp/screens/settings_screen.dart';
import 'package:flutter/material.dart';
import 'package:myapp/services/authentication.dart';
import 'package:provider/provider.dart';
class HomeScreen extends StatefulWidget {
@override
State<StatefulWidget> createState() => new _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
bool _isEmailVerified = false;
@override
void initState() {
super.initState();
_checkEmailVerification(); // <=== Method which should show Dialog box if email is not verified which is coming from "Auth" Provider
}
@override
Widget build(BuildContext context) {
final auth = Provider.of<Auth>(context, listen: false); // <==== Service from Provider, which contains data for _isEmailVerified
auth.isEmailVerified().then((value) => _isEmailVerified = value);
return new Scaffold(
appBar: new AppBar(
title: new Text('My App'),
),
body: Center(
child: Column(
children: <Widget>[
Text(
'Welcome to my app',
),
],
),
),
);
}
void _checkEmailVerification() async {
_isEmailVerified = auth.isEmailVerified(); // <=== How can I use "auth" from Provider to get isEmailVerified data ????
if (!_isEmailVerified) {
_showVerifyEmailDialog();
}
}
void _showVerifyEmailDialog() {
showDialog(
context: context,
builder: (BuildContext context) {
// return object of type Dialog
return AlertDialog(
title: new Text("Verify your account"),
content: new Text("Please verify account in the link sent to email"),
actions: <Widget>[
new FlatButton(
child: new Text("Resend link"),
onPressed: () {
Navigator.of(context).pop();
_resentVerifyEmail();
},
),
new FlatButton(
child: new Text("Dismiss"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
void _resentVerifyEmail() {
// Logic to send email
}
}
If you instead make an asynchronous call which delegates your call until after the widget has been initialized, you can then use context as you intend. A simple way to do that is to use a future. With more context from the OP provided in comments, I can give a slightly better solution to their specific problem.
Example Using Provider dart , all we have to do is call Provider. of<String>(context) , the of() method here will obtain the nearest Provider up its widget tree and returns its value. Also in the code above, we are reading the value, in this case there is no way to update unless we update the value in the code.
initState() is a method of class State and it is considered as an important lifecycle method in Flutter. initState() is called only Once and we use it for one time initializations. Example : To initialize data that depends on the specific BuildContext . To initialize data that needs to executed before build() .
You need to use the context to call Provider.of()
so you can add addPostFrameCallback()
which is called after the first build, there you can use the context
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
auth = Provider.of<Auth>(context, listen: false);
});
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With