After reading the documentation, it did not explain very well what ref.read()
, ref.watch()
, and ref.listen()
is.
The questions I have are as follows:
Use read
to the get the value of/in provider just once (one-time read)
Use watch
to the get the value of/in provider the first time and every time the value changes (see it like you're subscribing to the provider, so you get notified any time there's a change)
listen
is similar to watch
. The main difference is the return type.
watch
returns the new value directly, listen
returns a void
but gives access to the new value and the old value with a callback (See examples below)
You can use read
in places like initState
, callbacks like onPressed
etc. watch
and listen
should not be called asynchronously, like inside an onPressed
of an ElevatedButton. Nor should it be used inside initState
and other State life-cycles.
As Kaan Taha Köken pointed out:
AVOID using [read] for creating widgets with a value that never changes and CONSIDER using [Provider] or
select
for filtering unwanted rebuilds.
Use read
when you want to value of the provider only once.
Use watch
when you want to always get the value.
StateProvider
final counterProvider = StateProvider((ref) => 0);
class HomePage extends ConsumerWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final counter = ref.watch(counterProvider);
ref.listen(
counterProvider,
(previous, next) {
print("The new value is $next");
if (next == 5) {
print("I just reached 5");
}
},
);
return Scaffold(
body: Center(
child: Text(
counter.toString(),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
ref.read(counterProvider.state).state += 1;
},
),
);
}
}
The example above shows the use of watch
, read
and listen
.
watch
ing the counter
value so it gets updated in the UI anytime there is a change.listen
ing to the counter
to print the updated value and print I've reached 5
when it is 5.read
the provider state and add 1
when the FloatingActionButton
is pressed.