I’m working on a Flutter application using Riverpod for state management. I have a TextFormField with a TextEditingController to keep track of the entered value. The problem is when I enter a value into the TextFormField, the screen does not update accordingly. Moreover, the ElevatedButton in my application is not responsive (it can’t be pressed) even when the TextFormField is not empty.
Here is the snippet of my code:
final textFieldControllerProvider =
StateProvider<TextEditingController>((ref) => TextEditingController());
class MyWidget extends ConsumerWidget {
const MyWidget({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final controller = ref.watch(textFieldControllerProvider);
return Scaffold(
appBar: AppBar(
title: const Text("Riverpod example"),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
TextFormField(
controller: controller,
onChanged: (value) {
ref.watch(textFieldControllerProvider.notifier).state.text =
value;
},
),
ElevatedButton(
onPressed: controller.text.isNotEmpty
? () {
print('Button pressed with value');
}
: null,
child: const Text('Submit'),
),
],
),
),
);
}
}
Actual operation:
Our two main issues:
Button responsiveness: buttons do not work as expected, even though they are set to activate when the text from the controller is not empty.
Cursor movement: the cursor moves unexpectedly to the left whenever text is entered.
We suspect that both the button unresponsiveness and the cursor moving to the left may be related to the widget update process.
Any suggestions on how to resolve these issues would be appreciated.
2
Answers
The biggest issue is you’re using
ConsumerWidget
which works as a StatelessWidget. So, it will not going to update your screen. To update state you’ve to useConsumerStatefulWidget
orStatefulHookConsumerWidget
like below.ConsumerStatefulWidget Example
StatefulHookConsumerWidget Example
There are a number of errors in your code. Now I will help you fix them:
ref.watch
inside initState and callback. Useref.read
instead:TextEditingController
is. If you walk through the inheritance tree, it will look like this:This means that neither
Provider
norStateProvider
is adequate here. UseChangeNotifierProvider
for this purpose:Consumer
to avoid rebuilding the entire tree:I used
select
to keep track of only the field I want. In this case, we are trackingtext
. Although this does not really matter here, because.text
is part of the main state, which we don’t have access to.Your complete code will look like this:
Wrapper to run in dartpad:
Main code with all notes:
A simplified version would look like this (
MyWidget
will be rebuilt whenever the text changes):I also added
print
methods so you can see the rebuild moments in the console.Good coding!