[英]Stateful widget not rebuilding child widget when state changes (Flutter)
I'm building a form that signs up the user on Firebase, and where the ElevatedButton either displays "CREATE YOUR ACCOUNT" or a CircularProgressIndicator, based on the state of isLoading.我正在构建一个表单,用于在 Firebase 上注册用户,其中 ElevatedButton 显示“创建您的帐户”或 CircularProgressIndicator,基于 isLoading 的 state。 Yet, the button's child doesn't change based on isLoading.
然而,按钮的子元素不会根据 isLoading 改变。
The states does change -- I'm printing out isLoading in the middle of my onPressed methode, and I do see it as true .状态确实发生了变化——我在我的 onPressed 方法中间打印出 isLoading ,我确实认为它是true 。
Why isn't the button changing its child?为什么按钮不改变它的孩子?
import 'package:flutter/material.dart';
import 'package:tedy/components/custom_text_form_field.dart';
import 'package:tedy/components/custom_wrapper.dart';
class EmployerOnboardingOneView extends StatefulWidget {
const EmployerOnboardingOneView({Key? key}) : super(key: key);
@override
State<EmployerOnboardingOneView> createState() =>
_EmployerOnboardingOneViewState();
}
class _EmployerOnboardingOneViewState extends State<EmployerOnboardingOneView> {
var firstNameController = TextEditingController();
var lastNameController = TextEditingController();
var emailController = TextEditingController();
var passwordController = TextEditingController();
var passwordConfirmController = TextEditingController();
bool isLoading = false;
@override
Widget build(BuildContext context) {
var screenWidth = MediaQuery.of(context).size.width;
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
centerTitle: true,
title: SizedBox(
height: 50,
child: Image.asset(
'assets/images/tedy_logo_color.png',
filterQuality: FilterQuality.high,
),
),
),
body: CustomWrapper(
maxWidth: 400,
children: [
Text(
'Create a Tedy account for your company',
style: Theme.of(context).textTheme.headline3,
textAlign: TextAlign.center,
),
const SizedBox(
height: 20,
),
CustomTextFormField(
controller: firstNameController, label: 'First Name'),
const SizedBox(
height: 20,
),
CustomTextFormField(
controller: lastNameController, label: 'Last Name'),
const SizedBox(
height: 20,
),
CustomTextFormField(controller: emailController, label: 'Email'),
const SizedBox(
height: 20,
),
CustomTextFormField(
controller: passwordController,
isPassword: true,
label: 'Password'),
const SizedBox(
height: 20,
),
CustomTextFormField(
controller: passwordConfirmController,
isPassword: true,
label: 'Confirm your password'),
const SizedBox(
height: 20,
),
SizedBox(
width: double.infinity,
height: 50,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Theme.of(context).primaryColor),
onPressed: () async {
setState(() {
isLoading = true;
});
if (passwordController.text != passwordConfirmController.text) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Passwords must match'),
backgroundColor: Colors.red,
),
);
} else {
try {
FirebaseAuth.instance
.createUserWithEmailAndPassword(
email: emailController.text,
password: passwordController.text)
.then((value) {
Navigator.pushNamedAndRemoveUntil(
context, '/', (route) => false);
});
print(isLoading);
} on FirebaseAuthException catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(e.message != null
? e.message as String
: 'There was an error.'),
backgroundColor: Colors.red,
),
);
}
}
setState(() {
isLoading = false;
});
},
child: isLoading
? const SizedBox(
width: 30,
height: 30,
child: CircularProgressIndicator(
color: Colors.white,
),
)
: const Text('CREATE YOUR ACCOUNT'),
),
)
],
),
);
}
}
createUserWithEmailAndPassword is async, so you have to await it createUserWithEmailAndPassword 是异步的,所以你必须等待它
await FirebaseAuth.instance
.createUserWithEmailAndPassword(
email: emailController.text,
password: passwordController.text);
Navigator.pushNamedAndRemoveUntil(
context, '/', (route) => false);
Your code set isLoading to true, does the password logic and calls this method.您的代码集 isLoading 为 true,执行密码逻辑并调用此方法。 But since you don't await it here it just skips it and calls the setState with isLoading = false.
但是由于您不在这里等待它,它只是跳过它并使用 isLoading = false 调用 setState。
You are using then
for the future.您将
then
用于未来。 so the last isLoading = false;
所以最后一个
isLoading = false;
executed when you pressed the button.按下按钮时执行。 You can change state inside.then instead of end.
您可以更改 state inside.then 而不是 end。 Also you can add inside
FirebaseAuthException
.您也可以在
FirebaseAuthException
中添加。 make sure to remove last isLoading = false;
确保删除最后一个
isLoading = false;
FirebaseAuth.instance
.createUserWithEmailAndPassword(
email: emailController.text,
password: passwordController.text)
.then((value) {
setState(() {
isLoading = false;
});
Navigator.pushNamedAndRemoveUntil(
context, '/', (route) => false);
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.