Issue
I'm new to flutter development and trying to understand Riverpod.
I currently managed to make the following login form work with a StatefulWidget. Basically, the button becomes enabled if both fields are not empty and viceversa.
And this is the current code for it.
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;
}
}
What I don't like is how the listeners call setState
directly just to trigger a widget refresh. Is this how would you accomplish such a behavior?
I read great things about Riverpod, but I don't seem to grasp how to model the above behavior inheriting from HookWidget
instead of StatefulWidget
. Specifically, how to add the listeners to the text editing controllers.
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;
}
}
Any help or tips will be appreciated.
Solution
To update the changes on HookWidget
use useEffect(). We don't have to worry about dispose until create our custom 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"),
)
],
);
}
}
Answered By - Yeasin Sheikh
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.