【问题标题】:Failed to update the state using BlockBuilder() and TextField()'s onChanged property. [Flutter_Bloc]使用 BlockBuilder() 和 TextField() 的 onChanged 属性更新状态失败。 [Flutter_Bloc]
【发布时间】:2020-05-21 14:13:22
【问题描述】:

我正在尝试做一个简单的表单验证模型,但到目前为止,我无法使用 TextField() 的 onChanged 属性更新 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 的内容,但看起来它不会在 onChanged online 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";
    }
  }
}

谢谢

【问题讨论】:

    标签: flutter flutter-bloc


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      看起来问题出在这一行:

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-01-22
        • 2019-03-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-27
        相关资源
        最近更新 更多