使用BlockBuilder()和TextField()的onChanged属性无法更新状态。 [Flutter_Bloc]

时间:2020-05-21 14:13:22

标签: flutter flutter-bloc

我正在尝试做一个简单的表单验证模型,到目前为止,我无法使用TextField()的onChanged属性在BlocBuilder()下更新State。

这是我的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(),
        ),
      ),
    );
  }
}

这是需要根据输入更改进行更新的主文件。 “ $快照”应该根据其当前状态产生来自LoginBloc的信息,但看起来它并不会在onChanged在线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";
    }
  }
}

谢谢

2 个答案:

答案 0 :(得分:0)

问题似乎在这一行:

final LoginBloc bloc = BlocProvider.of<LoginBloc>(context);

您在错误的上下文中访问集团。删除该行并在要访问BlocProvider时直接使用LoginBloc

onChanged: (_) => BlocProvider.of<LoginBloc>(context).add(LoginEvent.username),

答案 1 :(得分:0)

您的应用中有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从树中自动找到

您还需要以不同的方式管理状态,否则在其中一个字段中键入将在两个字段中均显示错误