无法使用 BlockBuilder() 和 TextField() 的 onChanged 属性 更新状态。 [Flutter_Bloc]
Failed to update the state using BlockBuilder() and TextField()'s onChanged property. [Flutter_Bloc]
我正在尝试做一个简单的表单验证模型,到目前为止,我无法使用 TextField() 的 onChanged 属性.[=15 在 BlocBuilder() 下更新我的状态=]
这是我的 BlocProvider()
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Log me in',
home: Scaffold(
body: BlocProvider<LoginBloc>(
create: (context) => LoginBloc(),
child: LoginScreen(),
),
),
);
}
}
这是需要在输入更改时更新的主文件。
'$snapshot' 应该根据其当前状态产生来自 LoginBloc 的内容,但看起来它不会在在线更改 StreamBuilder()
上自行重建
lass LoginScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final LoginBloc bloc = BlocProvider.of<LoginBloc>(context);
return BlocBuilder<LoginBloc, String>(
bloc: LoginBloc(),
builder: (context, snapshot) {
return Container(
margin: EdgeInsets.all(10),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
// emailField(bloc),
TextField(
onChanged: (_) => bloc.add(LoginEvent.username),
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
hintText: 'example@email.com',
labelText: 'Email Address',
errorText: '$snapshot',
),
),
// passwordField(bloc),
TextField(
onChanged: (_) => bloc.add(LoginEvent.password),
keyboardType: TextInputType.visiblePassword,
decoration: InputDecoration(
hintText: 'Password',
labelText: 'Password',
errorText: '$snapshot',
),
),
SizedBox(
height: 25,
),
// submitButton(),
],
),
);
});
}
这是我的 LoginBloc()
class LoginBloc extends Bloc<LoginEvent, String> {
get initialState => '';
Stream<String> mapEventToState(LoginEvent event) async* {
switch (event) {
case LoginEvent.username:
if (state.contains('@')) {
yield 'Approved';
} else {
yield 'Please retry';
}
break;
case LoginEvent.password:
if (state.length > 3) {
yield 'Nice password';
}
yield "Please retry";
}
}
}
谢谢
看起来问题出在这一行:
final LoginBloc bloc = BlocProvider.of<LoginBloc>(context);
您在错误的上下文中访问了该集团。删除该行并在要访问 LoginBloc
:
时直接使用 BlocProvider
onChanged: (_) => BlocProvider.of<LoginBloc>(context).add(LoginEvent.username),
您的应用中有两个不同的 LoginBloc
实例。一个由 BlocProvider
创建并传递,第二个由您在 BlocBuilder
.
中创建
问题是您正在将事件添加到 BlocProvider's
集团中,而 BlocBuilder
正在监听另一个集团。
要解决此问题,您可以这样做
Widget build(BuildContext context) {
final LoginBloc bloc = BlocProvider.of<LoginBloc>(context);
return BlocBuilder<LoginBloc, String>(
bloc: bloc, // Pass the above bloc instance
builder: (context, snapshot) {
// rest as it is
}
)
}
奖励:- 您可以跳过 bloc: bloc
,因为它是一个可选参数,如果没有提供,它会使用 BlocProvider
从树中自动找到
您还需要以不同的方式管理状态,否则在其中一个字段中输入将在两个字段中显示错误
我正在尝试做一个简单的表单验证模型,到目前为止,我无法使用 TextField() 的 onChanged 属性.[=15 在 BlocBuilder() 下更新我的状态=]
这是我的 BlocProvider()
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Log me in',
home: Scaffold(
body: BlocProvider<LoginBloc>(
create: (context) => LoginBloc(),
child: LoginScreen(),
),
),
);
}
}
这是需要在输入更改时更新的主文件。 '$snapshot' 应该根据其当前状态产生来自 LoginBloc 的内容,但看起来它不会在在线更改 StreamBuilder()
上自行重建lass LoginScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final LoginBloc bloc = BlocProvider.of<LoginBloc>(context);
return BlocBuilder<LoginBloc, String>(
bloc: LoginBloc(),
builder: (context, snapshot) {
return Container(
margin: EdgeInsets.all(10),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
// emailField(bloc),
TextField(
onChanged: (_) => bloc.add(LoginEvent.username),
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
hintText: 'example@email.com',
labelText: 'Email Address',
errorText: '$snapshot',
),
),
// passwordField(bloc),
TextField(
onChanged: (_) => bloc.add(LoginEvent.password),
keyboardType: TextInputType.visiblePassword,
decoration: InputDecoration(
hintText: 'Password',
labelText: 'Password',
errorText: '$snapshot',
),
),
SizedBox(
height: 25,
),
// submitButton(),
],
),
);
});
}
这是我的 LoginBloc()
class LoginBloc extends Bloc<LoginEvent, String> {
get initialState => '';
Stream<String> mapEventToState(LoginEvent event) async* {
switch (event) {
case LoginEvent.username:
if (state.contains('@')) {
yield 'Approved';
} else {
yield 'Please retry';
}
break;
case LoginEvent.password:
if (state.length > 3) {
yield 'Nice password';
}
yield "Please retry";
}
}
}
谢谢
看起来问题出在这一行:
final LoginBloc bloc = BlocProvider.of<LoginBloc>(context);
您在错误的上下文中访问了该集团。删除该行并在要访问 LoginBloc
:
BlocProvider
onChanged: (_) => BlocProvider.of<LoginBloc>(context).add(LoginEvent.username),
您的应用中有两个不同的 LoginBloc
实例。一个由 BlocProvider
创建并传递,第二个由您在 BlocBuilder
.
问题是您正在将事件添加到 BlocProvider's
集团中,而 BlocBuilder
正在监听另一个集团。
要解决此问题,您可以这样做
Widget build(BuildContext context) {
final LoginBloc bloc = BlocProvider.of<LoginBloc>(context);
return BlocBuilder<LoginBloc, String>(
bloc: bloc, // Pass the above bloc instance
builder: (context, snapshot) {
// rest as it is
}
)
}
奖励:- 您可以跳过 bloc: bloc
,因为它是一个可选参数,如果没有提供,它会使用 BlocProvider
您还需要以不同的方式管理状态,否则在其中一个字段中输入将在两个字段中显示错误