I have built this riverpod state:
import "package:riverpod_annotation/riverpod_annotation.dart";
part "form_state.g.dart";
@riverpod
class FormState extends _$FormState {
@override
List<String?> build() {
ref.listenSelf((previous, next) {
log("previous: $previous, next: $next", name: "FORMSTATE 0");
});
return List.filled(10, null);
}
void change(int index, String value) {
log("change: $index, value: $value", name: "FORMSTATE 1");
state = [
...state.sublist(0, index),
value,
...state.sublist(index + 1),
];
}
}
On my Widget, I have a list of TextField
as Below:
class DummyPage extends ConsumerStatefulWidget {
const DummyPage({super.key});
@override
ConsumerState<DummyPage> createState() =>
_DummyPageState();
}
class _DummyPageState extends ConsumerState<DummyPage> {
final List<TextEditingController> _controllers =
List.generate(10.length, (index) => TextEditingController());
@override
void initState() {
final form = ref.read(formStateProvider);
for (var i = 0; i < _controllers.length; i++) {
_controllers[i].text = form[i] ?? "";
}
super.initState();
}
@override
void dispose() {
for (var i = 0; i < _controllers.length; i++) {
_controllers[i].dispose();
}
super.dispose();
}
@override
Widget build(context) {
return Column(children: [
...List.generate(
_controllers.length,
(index) => TextField(
controller: _controllers[index],
onChanged: (val) {
ref.read(formStateProvider.notifier).change(index, val);
}
)
])
}
The current condition is every time onChanged
is called, it always resets the value as below:
[FORMSTATE 0] previous: null, next: [null, null, null, null, null, null]
[FORMSTATE 1] change: 0, value: 2
[FORMSTATE 0] previous: [null, null, null, null, null, null], next: [2, null, null, null, null, null]
[FORMSTATE 0] previous: null, next: [null, null, null, null, null, null]
[FORMSTATE 1] change: 1, value: 3
[FORMSTATE 0] previous: [null, null, null, null, null, null], next: [null, 3, null, null, null, null]
[FORMSTATE 0] previous: null, next: [null, null, null, null, null, null]
[FORMSTATE 1] change: 2, value: 9
[FORMSTATE 0] previous: [null, null, null, null, null, null], next: [null, null, 9, null, null, null]
My question is what causes this? How to change it to fulfill the expected case when a particular TextField
in list of TextField
at index i
changes, the riverpod state at index i
will also change?
There is no listener for your notifier and therefore it is auto disposed.
You can verify it by adding a log statement with ref.dispose
inside the notifier or setup a ProviderObserver
.
https://docs-v2.riverpod.dev/docs/concepts/provider_observer
You could change the behaviour by adding ref.watch(formStateProvider);
or ref.listen(formStateProvider);
inside the widget's build
method or set the notifier's keepAlive
to true.