I’m working with Flutter Riverpod and have encountered different behaviors when using ref.watch versus ref.read in my DumTabNotifier class. Here’s a simplified version of my code:
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:get/get.dart';
// Notifier class
class DumTabNotifier extends Notifier<DumTabState> {
final _edtLmp = TextEditingController();
@override
DumTabState build() {
ref.onDispose(() {
_edtLmp.clear();
});
return DumTabState(
gestationalAgeString: '',
edd: '',
eofTrimester: '',
bofTrimester: '',
gaWeeks: 0,
gaDays: 0,
edtLmp: _edtLmp,
);
}
void calculateFromLmp() {
DateTime? lmpDT = extractDateFromStringBasedOnLocale(_edtLmp.text);
if (lmpDT == null) return;
final todayGlobal = ref.watch(todayGlobalProvider); // or ref.read(todayGlobalProvider)
// Calculation logic...
}
}
final dumTabProvider = NotifierProvider<DumTabNotifier, DumTabState>(() {
return DumTabNotifier();
});
Issue:
When I use ref.watch(todayGlobalProvider) inside calculateFromLmp(), the DumTabNotifier gets disposed and recreated if the todayGlobalProvider changes. I discovered this because the TextEditingController (_edtLmp) clears itself (unwanted behavior) whenever ref.watch is used, indicating that the notifier is being disposed. However, when I replace ref.watch with ref.read(todayGlobalProvider), the DumTabNotifier is not disposed when todayGlobalProvider changes.
Question:
Why does using ref.watch cause the DumTabNotifier to be disposed and recreated, while ref.read does not?
What are the best practices for deciding when to use ref.watch versus ref.read in this context?
Any insights into the behavior and lifecycle management of Riverpod notifiers would be greatly appreciated!
Edit: now I’ve discovered (on riverpod doc) that provider is not recommended to be used with TextEditingControllers. However I do need to access this TextEditingController from several screens.
2
Answers
Ref.read
The ref.read method is a way to obtain the state of a provider without listening to it.
It is commonly used inside functions triggered by user interactions.
DON’T use ref.read inside the build method
Ref.watch
ref.watch is used inside the build method of a widget or inside the body of a provider to have the widget/provider listen to a provider
The watch method should not be called asynchronously, like inside an onPressed of an ElevatedButton. Nor should it be used inside initState and other State life-cycles.In those cases, consider using ref.read instead.
The problem Is on Watch(): It Is used to register the notifier against the context. If you do so, It would be created (if no One Is already present) or, in your case, It Would be destroyed perhaps the widget was be recreated . In the other case if you call read(), It Will not follow the widget Life cycle, It Will execute the function of the listener without any registration. Moreover you should use flutter hooks tò handle this kind of states, and use riverpod only for Global states.