Как использовать HookWidget с useTextEditingController
Я новичок в разработке и пытаюсь понять 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;
}
}
Любая помощь или советы будут оценены.
2 ответа
Чтобы обновить изменения на
HookWidget
используйте useEffect () . Нам не нужно беспокоиться об удалении, пока не создадим наш собственный hookWidget.
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"),
)
],
);
}
}
Вам просто нужно всего лишь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"),
)
],
);
}
}