Flutter Riverpod ref.read() vs ref.listen() vs ref.watch()
What is the purpose and difference between these functions?
read()
Use read
to the get the value of/in provider just once (one-time read)
watch()
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()
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)
Where and where not can I use these functions?
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.
When should I use these functions?
read()
Use read
when you want to value of the provider only once.
watch()
Use watch
when you want to always get the value.
Example: Counter app with 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
.
- We're
watch
ing thecounter
value so it gets updated in the UI anytime there is a change. - We're
listen
ing to thecounter
to print the updated value and printI've reached 5
when it is 5. - To increment the value, we
read
the provider state and add1
when theFloatingActionButton
is pressed.
Vraj Shah
I am a computer science student just trying my best to learn as much I possibly can about programming and helping others based on my findings.
Updated on January 04, 2023Comments
-
Vraj Shah over 1 year
After reading the documentation, it did not explain very well what
ref.read()
,ref.watch()
, andref.listen()
is.The questions I have are as follows:
- What is the purpose and difference between these functions?
- Where and where not can I use these functions?
- When should I use these functions?
-
Richard about 2 yearsYour answer links to the same documentation the question links to, which he just said doesn't explain it very well.
-
Kaan Taha Köken almost 2 yearsit is not advised to use
read
inside build method. It is already mentioned in the docs. Also, for the sake of counter-example, instead of usingref.read
, it is suggesting different approach. -
Kaan Taha Köken almost 2 yearsriverpod.dev/docs/concepts/reading checkout the lower section of this page
-
Josteve almost 2 years@KaanTahaKöken,
ref.read
can be called anywhere, while it's not advised - If you have a particular use case (say you only want to read an object just once and you don't want it to get updated) then using it is very fine. -
Josteve almost 2 yearsFor the counter example in the documentation, the example was written using a
StateNotifierProvider
but it doesn't mean writing the counter app withStateProvider
is wrong - In fact, usingStateProvider
for a simpleCounter
app (as seen in the example) is more advisable. -
Kaan Taha Köken almost 2 yearsIf you hover over
ref.read
it gives the exact use case. Usingref.read
especially insideConsumerWidget's
build gave me a lot of headaches. The only use case that I prefer using on onTap/onPressed. Generally, prefer using watch with select -
Josteve almost 2 yearsI guess you're right, I've updated my answer.