I'm building an app with flutter and I have a question about Provider.of
. In my Widget
I call this :
Provider.of<Auth>(context, listen: false).signup(emailController.text, passwordController.text);
And I would like to navigate with Navigator
according to the return of my signup
function.
I tried multiple other ways but couldn't make it work.
Naively I tried this:
onPressed: () {
var result = Provider.of<Auth>(context, listen: false)
.signup(emailController.text,
passwordController.text);
if (result == "failed") {
Navigator.of(context).push(MaterialPageRoute(
builder: (ctx) => SuccessfulScreen()));
} else {
Navigator.of(context).push(MaterialPageRoute(
builder: (ctx) => UnsuccessfulScreen()));
}
},
But I got this type for the var result
: Future<String>
Here is my tree of my project:
lib/
├── firebase_options.dart
├── images
├── main.dart
├── model
│ └── apis
│ └── auth.dart
└── view
└── screens
├── login_screen.dart
├── signup_screen.dart
├── successful_screen.dart
└── welcome_screen.dart
And the auth.dart
contains this :
import 'package:flutter/foundation.dart';
import 'package:firebase_auth/firebase_auth.dart';
class Auth with ChangeNotifier {
Future<String> signup(String email, String password) async {
try {
await FirebaseAuth.instance.createUserWithEmailAndPassword(
email: email,
password: password,
);
} on FirebaseAuthException catch (e) {
if (e.code == 'weak-password') {
return e.code;
} else if (e.code == 'email-already-in-use') {
return e.code;
}
} catch (e) {
return e.toString();
}
return "succes";
}
Future<void> login(String email, String password) async {
try {
await FirebaseAuth.instance
.signInWithEmailAndPassword(email: email, password: password);
} on FirebaseAuthException catch (e) {
if (e.code == 'user-not-found') {
print('No user found for that email.');
} else if (e.code == 'wrong-password') {
print('Wrong password provided for that user.');
}
}
}
}
I could make this logic directly in my build function (login_screen.dart
) but I found that not easy to maintain. So I make it difficult for me but my guess is that I'm missing something, could someone help me on this ?
CodePudding user response:
Add the "async" keyword in the body of function and the "await" keyword before the call of your signup method, like this.
onPressed: () async {
var result = await Provider.of<Auth>(context, listen: false)
.signup(emailController.text,
passwordController.text);
if (result == "failed") {
Navigator.of(context).push(MaterialPageRoute(
builder: (ctx) => SuccessfulScreen()));
} else {
Navigator.of(context).push(MaterialPageRoute(
builder: (ctx) => UnsuccessfulScreen()));
}
},
CodePudding user response:
I often do this using callbacks:
class ClientManager extends ChangeNotifier {
final FirebaseAuth auth = FirebaseAuth.instance;
Client? client;
bool _loading = false;
bool get loading => _loading;
set loading(bool value) {
_loading = value;
notifyListeners();
}
Future<void> signUP({
required Client client,
required Function(String) onFail,
required Function() onSuccess,
}) async {
loading = true;
try {
final UserCredential result = await auth.createUserWithEmailAndPassword(
email: client.email!, password: client.password!);
client.id = result.user!.uid;
this.client = client;
await client.saveData();
onSuccess();
} on FirebaseAuthException catch (e) {
loading = false;
onFail(e.code);
}
loading = false;
}
}
Consumer<ClientManager>(
builder: (_, clientManager, __) {
return ElevatedButton(
onPressed: clientManager.loading
? null
: () {
clientManager.signUP(
client: client,
onFail: (e) {
ScaffoldMessenger.of(context)
.showSnackBar(
SnackBar(
backgroundColor:
Theme.of(context).errorColor,
content: const Text(
'Register'),
),
);
},
onSuccess: () {
Navigator.of(context)
.pushReplacementNamed('/');
},
);
},
child: clientManager.loading
? const SizedBox(
width: 25,
height: 25,
child: OSCircularIndicator())
: Text(AppLocalizations.of(context)!.login,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold)),
);
}
),