1

我正在尝试做一个简单的表单验证模型,到目前为止,我无法使用 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 在线 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";
    }
  }
}

谢谢

4

2 回答 2

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 从树中自动找到

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

于 2020-05-21T15:46:28.760 回答
0

看起来问题出在这一行:

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

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

onChanged: (_) => BlocProvider.of<LoginBloc>(context).add(LoginEvent.username),
于 2020-05-21T14:34:10.580 回答