flutter 如何在useTextEditingController中使用HookWidget

oxf4rvwz  于 2023-06-07  发布在  Flutter
关注(0)|答案(2)|浏览(168)

我是Flutter开发的新手,并试图了解Riverpod。
我目前设法使下面的登录表单与StatefulWidget一起工作。基本上,如果两个字段都不为空,则按钮变为启用,反之亦然。

这是它的当前代码。

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Login Demo',
      // theme: ThemeData(
      //   primarySwatch: Colors.blue,
      // ),
      home: Scaffold(
        body: Center(
          child: SizedBox(
            width: 400,
            child: MyLoginPage2(),
          ),
        ),
      ),
    );
  }
}

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

  @override
  State<MyLoginPage> createState() => _MyLoginState();
}

class _MyLoginState extends State<MyLoginPage> {
  final emailController = TextEditingController(text: '');
  final passwordController = TextEditingController(text: '');

  @override
  void initState() {
    super.initState();
    emailController.addListener(() {
      setState(() {});
    });
    passwordController.addListener(() {
      setState(() {});
    });
  }

  @override
  void dispose() {
    emailController.dispose();
    passwordController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        TextField(
          controller: emailController,
          keyboardType: TextInputType.emailAddress,
        ),
        TextField(
          controller: passwordController,
          obscureText: true,
        ),
        areFieldsEmpty()
            ? const ElevatedButton(
                child: Text('Login disabled'),
                onPressed: null,
              )
            : ElevatedButton(
                child: const Text('Login enabled'),
                onPressed: () => print("this is where login happens"),
              )
      ],
    );
  }

  bool areFieldsEmpty() {
    return emailController.text.toString().isEmpty ||
        passwordController.text.toString().isEmpty;
  }
}

我不喜欢的是侦听器直接调用setState来触发小部件刷新。你是这样做的吗?
我读了很多关于Riverpod的文章,但我似乎不知道如何对从HookWidget继承而不是从StatefulWidget继承的上述行为进行建模。具体来说,就是如何将侦听器添加到文本编辑控制器中。

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Login Demo',
      // theme: ThemeData(
      //   primarySwatch: Colors.blue,
      // ),
      home: Scaffold(
        body: Center(
          child: SizedBox(
            width: 400,
            child: MyLoginPage2(),
          ),
        ),
      ),
    );
  }
}

class MyLoginPage2 extends HookWidget {
  final emailController = useTextEditingController(text: '');
  final passwordController = useTextEditingController(text: '');

  MyLoginPage2({Key? key}) : super(key: key);

  // Pending questions
  // 1. Where do I add the listeners to the controllers?
  // 2. They are supposed to be auto dispose, right?

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        TextField(
          controller: emailController,
          keyboardType: TextInputType.emailAddress,
        ),
        TextField(
          controller: passwordController,
          obscureText: true,
        ),
        areFieldsEmpty()
            ? const ElevatedButton(
                child: Text('Login disabled'),
                onPressed: null,
              )
            : ElevatedButton(
                child: const Text('Login enabled'),
                onPressed: () => print("this is where login happens"),
              )
      ],
    );
  }

  bool areFieldsEmpty() {
    return emailController.text.toString().isEmpty ||
        passwordController.text.toString().isEmpty;
  }
}

任何帮助或提示将不胜感激。

mf98qq94

mf98qq941#

要更新HookWidget上的更改,请使用useEffect()。在创建自定义hookWidget之前,我们不必担心dispose。

class MyLoginPage2 extends HookWidget {
  const MyLoginPage2({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final emailController = useTextEditingController(text: '');
    final passwordController = useTextEditingController(text: '');

    final _areFieldsEmpty =
        useState<bool>(true); // controll the button based on Text.isEmpty

    bool areFieldsEmpty() {
      return emailController.text.toString().isEmpty ||
          passwordController.text.toString().isEmpty;
    }

    useEffect(() {
      emailController.addListener(() {
        _areFieldsEmpty.value = areFieldsEmpty();
      });
      passwordController.addListener(() {
        _areFieldsEmpty.value = areFieldsEmpty();
      });
    }, [
      emailController,
      passwordController,
    ]);
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        TextField(
          controller: emailController,
          keyboardType: TextInputType.emailAddress,
        ),
        TextField(
          controller: passwordController,
          obscureText: true,
        ),
        _areFieldsEmpty.value
            ? const ElevatedButton(
                child: Text('Login disabled'),
                onPressed: null,
              )
            : ElevatedButton(
                child: const Text('Login enabled'),
                onPressed: () => print("this is where login happens"),
              )
      ],
    );
  }
}
gojuced7

gojuced72#

你只需要useTextEditingController();.value方法。

class MyLoginPage2 extends HookWidget {
  const MyLoginPage2({Key? key}) : super(key: key);
  
  @override
  Widget build(BuildContext context) {
    final emailController = useTextEditingController();
    final passwordController = useTextEditingController();
    final _areFieldsEmpty = emailController.value.text.isEmpty && 
    passwordController.value.text.isEmpty;

    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        TextField(
          controller: emailController,
          keyboardType: TextInputType.emailAddress,
        ),
        TextField(
          controller: passwordController,
          obscureText: true,
        ),
        _areFieldsEmpty
            ? const ElevatedButton(
                child: Text('Login disabled'),
                onPressed: null,
              )
            : ElevatedButton(
                child: const Text('Login enabled'),
                onPressed: () => print("this is where login happens"),
              )
      ],
    );
  }
}

相关问题