如何在 Flutter 中使用全局键制作 StatefulWidget?

How to make StatefulWidget with global key in Flutter?

我是 Flutter 的新手,我想我的设置可能很奇怪。到目前为止的大部分设置都来自小型教程。我目前 main.dart 只呈现一个 userCheck 小部件,它最终将用于连接后端并检查我是否拥有有效的用户令牌。

class UserCheck extends StatefulWidget {
  const UserCheck({Key key}) : super(key: key);

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

class UserCheckState extends State<UserCheck> {
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  var userExists = false;

  @override
  Widget build(BuildContext context) {
    return userExists
        ? Home()
        : new LoginForm();
  }
}

如果有合适的用户,Home Widget 最终会从后端加载信息。现在,userExists 显然默认为 false。这会很好地加载 LoginForm。我目前的目标是当用户登录时,假设这是一个好的登录,然后将 userExists 反转为 true,从而打开主页。这是登录表单设置:

  LoginForm({Key key}) : super(key: key);
  UserCheckState parent;

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

class LoginFormState extends State<LoginForm> {
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  var userData = {};
  bool login = true;
  String loginText = 'Sign Up';

  void updateField(String value, String field) {
    setState(() {
      userData = {
        ...userData,
        '$field': value,
      };
    });
  }

  void sendHome() {
    setState(() {
      // this.parent.parent.userExists = true;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Column(children: <Widget>[
        login
            ? Form(
                key: _formKey,
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    TextFormField(
                      decoration: const InputDecoration(
                          hintText: 'Enter a username', labelText: 'Username'),
                      validator: (String value) {
                        if (value == null || value.isEmpty) {
                          return 'Please enter a username';
                        }
                        updateField(value, 'username');
                        return null;
                      },
                    ),
                    TextFormField(
                      obscureText: true,
                      enableSuggestions: false,
                      autocorrect: false,
                      decoration: const InputDecoration(
                          hintText: 'Enter your password',
                          labelText: 'Password'),
                      validator: (String value) {
                        if (value == null || value.isEmpty) {
                          return 'Please enter a password';
                        }
                        updateField(value, 'password');
                        return null;
                      },
                    ),
                    Padding(
                      padding: const EdgeInsets.symmetric(vertical: 16.0),
                      child: ElevatedButton(
                        onPressed: () {
                          print('hit here');
                          if (_formKey.currentState.validate()) {
                            print('hit here two');
                            sendHome();
                            print(userData);
                            // if API responds with proper token

                            // API call to login
                          }
                        },
                        child: Text('Submit'),
                      ),
                    ),
                  ],
                ),
              )
            : SignupForm(),
        ElevatedButton(
          onPressed: () {
            setState(() {
              login = !login;
              loginText = loginText == 'Sign Up' ? 'Log In' : 'Sign Up';
            });
          },
          child: Text(loginText),
        )
      ]),
    );
  }
}```

I don't know if there's some sort of router that would be better and is already implemented as switching Widgets, but I haven't found anything from my own searches.

如果用户登录,您不必返回到 userCheck 小部件。相反,您可以使用 Navigator 直接转到 Home 屏幕,使从 Login 页面到 Home 页面的转换。将导航器放在用户在 Submit 按钮的 onPressed 函数中获取有效令牌的行之后:

ElevatedButton(
  onPressed: () {
    if (_formKey.currentState.validate()) {
      // Goes to Home screen.
      Navigator.of(context).push(MaterialPageRoute(
        builder: (context) => Home(),
      ));
    }
  },
  child: Text('Submit'),
),