简体   繁体   English

FLUTTER MOBX:构建函数返回 null。 相关的导致错误的小部件是观察者

[英]FLUTTER MOBX: A build function returned null. The relevant error-causing widget was Observer

I'm trying to do a verification in two fields, email and password, using MOBX , and I'm computing the result of two functions, in a compuntig called formIsValid, but mobX has returned this error to me: A build function returned null.我试图做使用MOBX在两个领域,电子邮件地址和密码,验证,和我计算的两个函数的结果,在一个名为formIsValid compuntig,但mobX返回这个错误给我:一个构建函数返回null . The relevant error-causing widget was Observer相关的导致错误的小部件是观察者

I tried to do it in different ways and I can't, and besides that my email observables emailErrorLabel and passwordErrorLabel are not affecting the TextTormField errorText.我试图以不同的方式做到这一点,但我不能,而且我的电子邮件可观察值emailErrorLabelpasswordErrorLabel不会影响TextTormField errorText。

Here is my code ViewModel:这是我的代码视图模型:

import 'package:covid_app/app/service/firebase/firebase_auth.dart';
import 'package:covid_app/app/service/firebase/firebase_auth_impl.dart';
import 'package:covid_app/app/ui/home/home_page.dart';
import 'package:flutter/material.dart';
import 'package:mobx/mobx.dart';

part 'login_viewmodel.g.dart';

class LoginViewModel = LoginViewModelBase with _$LoginViewModel;

abstract class LoginViewModelBase with Store {
  @observable
  String email = "";

  @observable
  String password = "";

  @observable
  bool error = false;

  @observable
  bool emailErrorLabel = false;

  @observable
  bool passwordErrorLabel = false;

  final _auth = Auth();

  @action
  changeEmail(String newEmail) => email = newEmail;

  @action
  changePassword(String newPassword) => password = newPassword;

  @action
  setHasErrorOnEmail(bool value) => emailErrorLabel = value;

  @action
  setHasErrorOnPassword(bool value) => passwordErrorLabel = value;

  bool emailIsValid() {
    if (email.isNotEmpty && email.contains("@")) {
      return true;
    } else {
      setHasErrorOnEmail(true);
      return false;
    }
  }

  bool passwordIsValid() {
    if (password.isNotEmpty || password.length >= 8) {
      return true;
    } else {
      setHasErrorOnPassword(true);
      return false;
    }
  }

  @computed
  bool get formIsValid {
    return emailIsValid() && passwordIsValid();
  }

  @action
  Future<void> firebaseLogin(dynamic context) async {
    try {
      if (email.isNotEmpty && password.isNotEmpty) {
        var userId;
        await _auth.signIn(email, password).then((value) => userId = value);
        userId.length > 0 ? homeNavigator(context) : error = true;
      } else {
        error = true;
      }
    } catch (Exception) {
      error = true;
      print("Login Error: $Exception");
    }
  }

  void homeNavigator(context) {
    Navigator.push(
        context, MaterialPageRoute(builder: (context) => HomePage()));
  }
}

My LoginPage:我的登录页面:

import 'package:covid_app/app/ui/login/login_viewmodel.dart';
import 'package:covid_app/app/widgets/KeyboardHideable.dart';
import 'package:covid_app/core/constants/colors.dart';
import 'package:covid_app/core/constants/dimens.dart';
import 'package:covid_app/core/constants/string.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import '../../widgets/button_component.dart';
import 'widgets/text_form_field_component.dart';

class LoginPage extends StatefulWidget {
  @override
  _LoginPageState createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  var vm = LoginViewModel();
  var value = zero;
  var valueTextFields = sixtyEight;
  TextEditingController controllerEmail = TextEditingController();
  TextEditingController controllerPassword = TextEditingController();

  void animatedTest() async {
    Future.delayed(Duration(seconds: 0), () {
      setState(() {
        value = sixtyEight;
        valueTextFields = zero;
      });
    });
  }

  @override
  void initState() {
    super.initState();
    animatedTest();
  }

  @override
  Widget build(BuildContext context) {
    return KeyboardHideable(
      child: Scaffold(
        backgroundColor: darkPrimaryColor,
        body: SingleChildScrollView(
          child: Container(
            height: MediaQuery.of(context).size.height,
            child: SafeArea(
              child: Center(
                child: Padding(
                  padding: const EdgeInsets.all(sixteen),
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      Expanded(
                        child: Card(
                          elevation: twelve,
                          shape: RoundedRectangleBorder(
                            borderRadius:
                                BorderRadius.all(Radius.circular(twentyFour)),
                          ),
                          child: Padding(
                            padding: const EdgeInsets.all(thirtyTwo),
                            child: Column(
                              mainAxisAlignment: MainAxisAlignment.center,
                              children: <Widget>[
                                Spacer(),
                                Expanded(
                                  flex: 8,
                                  child: AnimatedContainer(
                                      margin: EdgeInsets.only(bottom: value),
                                      duration: Duration(seconds: 1),
                                      child: Image.asset(
                                          "assets/images/logo_covid_app.png")),
                                ),
                                Expanded(
                                  flex: 7,
                                  child: AnimatedContainer(
                                    margin:
                                        EdgeInsets.only(top: valueTextFields),
                                    duration: Duration(seconds: 1),
                                    child: Column(
                                      children: <Widget>[
                                        Expanded(
                                          flex: 2,
                                          child: Observer(
                                            builder: (_) =>
                                                TextFormFieldComponent(
                                                    emailHintText,
                                                    false,
                                                    controllerEmail,
                                                    vm.changeEmail,
                                                    vm.emailErrorLabel,
                                                    emailErrorLabel),
                                          ),
                                        ),
                                        Expanded(
                                          flex: 2,
                                          child: Observer(builder: (_) {
                                            return TextFormFieldComponent(
                                                passwordHintText,
                                                true,
                                                controllerPassword,
                                                vm.changePassword,
                                                vm.emailErrorLabel,
                                                passwordErrorLabel);
                                          }),
                                        ),
                                      ],
                                    ),
                                  ),
                                ),
                                SizedBox(
                                  height: twentyEight,
                                ),
                                Expanded(
                                  flex: 2,
                                  child: Observer(
                                    builder: (_) => ButtonComponent(
                                      title: loginButtonLabel,
                                      fillColor: rosePrimaryColor,
                                      textColor: Colors.white,
                                      loginFun: vm.formIsValid
                                          ? () => vm.firebaseLogin(context)
                                          : null,
                                    ),
                                  ),
                                ),
                                SizedBox(
                                  height: twenty,
                                ),
                                Expanded(
                                  flex: 2,
                                  child: ButtonComponent(
                                      title: registerButtonLabel,
                                      fillColor: darkPrimaryColor,
                                      textColor: Colors.white,
                                      loginFun: () {}),
                                ),
                                Spacer()
                              ],
                            ),
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

My TextFormField Component:我的 TextFormField 组件:

import 'package:covid_app/core/constants/colors.dart';
import 'package:covid_app/core/constants/dimens.dart';
import 'package:flutter/material.dart';

// ignore: must_be_immutable
class TextFormFieldComponent extends StatefulWidget {
  String hintText;
  bool hideText;
  TextEditingController genericControler;
  bool genericValidation;
  String errorMessage;
  Function onChangedGeneric;

  TextFormFieldComponent(this.hintText, this.hideText, this.genericControler,
      this.onChangedGeneric, this.genericValidation, this.errorMessage);

  @override
  _TextFormFieldComponentState createState() => _TextFormFieldComponentState();
}

class _TextFormFieldComponentState extends State<TextFormFieldComponent> {
  @override
  Widget build(BuildContext context) {
    return Theme(
      data:
          ThemeData(cursorColor: rosePrimaryColor, hintColor: darkPrimaryColor),
      child: TextFormField(
        onChanged: widget.onChangedGeneric,
        controller: widget.genericControler,
        obscureText: widget.hideText,
        decoration: InputDecoration(
          hintText: widget.hintText,
          errorText: widget.genericValidation == true ? widget.errorMessage : null,
          border: OutlineInputBorder(
            borderRadius: BorderRadius.all(Radius.circular(twentyFour)),
          ),
          enabledBorder: OutlineInputBorder(
            borderRadius: BorderRadius.all(Radius.circular(twentyFour)),
            borderSide: BorderSide(width: two, color: darkPrimaryColor),
          ),
          focusedBorder: OutlineInputBorder(
            borderRadius: BorderRadius.all(Radius.circular(twentyFour)),
            borderSide: BorderSide(
              width: two,
              color: rosePrimaryColor,
            ),
          ),
        ),
      ),
    );
  }
}

My Button Component:我的按钮组件:

import 'package:covid_app/core/constants/colors.dart';
import 'package:covid_app/core/constants/dimens.dart';
import 'package:flutter/material.dart';

// ignore: must_be_immutable
class ButtonComponent extends StatefulWidget {
  var title;
  var fillColor;
  var textColor;
  Function loginFun;
  ButtonComponent({Key key, this.title, this.fillColor, this.textColor, this.loginFun});

  @override
  _ButtonComponentState createState() => _ButtonComponentState();
}

class _ButtonComponentState extends State<ButtonComponent> {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: hundredSeventyTwo,
      height: fortyFour,
      child: RaisedButton(
        disabledColor: Colors.grey,
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(
            twentyFour,
          ),
        ),
        onPressed: widget.loginFun,
        color: widget.fillColor,
        child: Text(
          widget.title,
          style: TextStyle(
            color: widget.textColor,
          ),
        ),
      ),
    );
  }
}

Print of the Error: https://i.stack.imgur.com/UmQd5.png / https://i.stack.imgur.com/K13rN.png错误打印: https : //i.stack.imgur.com/UmQd5.png / https://i.stack.imgur.com/K13rN.png

Well, the error says it all, nothing to add really.好吧,错误说明了一切,实际上没有什么可添加的。

Inside formIsValid computed you invoke 2 functions which in turn might modify emailErrorLabel or passwordErrorLabel and, since they both observable and are used in the same render, this is not allowed.formIsValid计算中,您调用 2 个函数,这些函数可能会修改emailErrorLabelpasswordErrorLabel并且由于它们都是observable并且在同一渲染中使用,因此这是不允许的。

computed should be pure function without side effects, it should just derive some value from other computed , observable or constant values. computed应该是没有副作用的纯函数,它应该只是从其他computed值、 observable值或常量值中获取一些值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 一个构建函数返回 null ,相关的导致错误的小部件是:StreamBuilder<EzuserData> - A build function returned null ,The relevant error-causing widget was : StreamBuilder<EzuserData> 在 null 上调用了方法“&gt;”。 接收方:null 尝试调用:&gt;(1e-10) 相关的导致错误的小部件是 Column - The method '>' was called on null. Receiver: null Tried calling: >(1e-10) The relevant error-causing widget was Column Flutter dart 错误(相关的导致错误的小部件是...) - Flutter dart error (The relevant error-causing widget was ...) flutter 错误,相关的导致错误的小部件是 Scaffold - flutter error , The relevant error-causing widget was Scaffold flutter layout, Listview builder 导致错误的相关小部件是:ListView - flutter layout, Listview builder The relevant error-causing widget was: ListView 在构建 Builder(dirty) 时引发了以下 NoSuchMethodError:在 null 上调用了方法“&gt;=”。 接收器:null 相关的错误原因是: - The following NoSuchMethodError was thrown building Builder(dirty): The method '>=' was called on null. Receiver: null The relevant error-causing was: 相关的导致错误的小部件是:Scaffold - The relevant error-causing widget was: Scaffold 导致错误的相关小部件是 TextField - The relevant error-causing widget was TextField 相关的导致错误的小部件是 Scaffold - The relevant error-causing widget was Scaffold 导致错误的相关小部件是:FutureBuilder<firebaseapp></firebaseapp> - The relevant error-causing widget was: FutureBuilder<FirebaseApp>
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM