website/docs/concepts2/consumers.mdx
import { Link } from "/src/components/Link";
A "Consumer" is a type of widget that bridges the gap between the Widget tree and the Provider tree.
The only real difference between a Consumer and typical widgets is that Consumers get access to a Ref. This enables them to read providers and listen to their changes. See <Link documentID="concepts2/refs" /> for more information.
Consumers come in a few different flavors, mostly for personal preference. You will find:
StatelessWidget or StatefulWidget.
// We subclass StatelessWidget as usual
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
// A FutureBuilder-like widget
return Consumer(
// The "builder" callback gives us a "ref" parameter
builder: (context, ref, _) {
// We can use that "ref" to listen to providers
final value = ref.watch(myProvider);
return Text(value.toString());
},
);
}
}
StatelessWidget widget.
Instead of subclassing StatelessWidget, you subclass ConsumerWidget. It will behave the same,
besides the fact that build receives an extra WidgetRef parameter.
// We subclass ConsumerWidget instead of StatelessWidget
class MyWidget extends ConsumerWidget {
// "build" receives an extra parameter
@override
Widget build(BuildContext context, WidgetRef ref) {
// We can use that "ref" to listen to providers
final value = ref.watch(myProvider);
return Text(value.toString());
}
}
StatefulWidget widget.StatefulWidget, you subclass ConsumerStatefulWidget.
And instead of State, you subclass ConsumerState.
The unique part is that ConsumerState has a ref property.
// We subclass ConsumerStatefulWidget instead of StatefulWidget
class MyWidget extends ConsumerStatefulWidget {
@override
ConsumerState<MyWidget> createState() => _MyWidgetState();
}
// We subclass ConsumerState instead of State
class _MyWidgetState extends ConsumerState<MyWidget> {
// A "this.ref" property is available
@override
Widget build(BuildContext context) {
// We can use that "ref" to listen to providers
final value = ref.watch(myProvider);
return Text(value.toString());
}
}
Alternatively, you will find extra consumers in the hooks_riverpod package. Those combine Riverpod consumers with flutter_hooks. If you don't care about hooks, you can ignore them.
The choice of which consumer to use is mostly a matter of personal preference.
You could use Consumer for everything. It is a slightly more verbose option than the others.
But this is a reasonable price to pay if you do not like how Riverpod hijacks StatelessWidget and StatefulWidget.
But if you do not have a strong opinion, we recommend using ConsumerWidget (or ConsumerStatefulWidget when you need a State).
StatelessWidget + context.watch?In alternative packages like provider, you can use context.watch to listen to providers.
This works inside any widget, as long as you have a BuildContext. So why isn't this the case in Riverpod?
The reason is that relying purely on BuildContext instead of a Ref would prevent the implementation
of Riverpod's <Link documentID="concepts2/auto_dispose" /> in a reliable way. There are tricks to make
an implementation that "mostly works" with BuildContext.
The problem is that there are lots of subtle edge-cases which could silently break the auto-dispose feature.
This would cause memory leaks, but that's not the real issue.
Automatic disposal is more importantly about stopping the execution of code that is no longer needed.
If auto-dispose fails to dispose a provider, then that provider may continuously perform
network requests in the background.
Riverpod preferred to not compromise on reliability for the sake of a little convenience.
:::note
To alleviate the downsides of having to use ConsumerWidget/ConsumerStatefulWidget instead of StatelessWidget/StatefulWidget,
Riverpod offers various refactors in IDEs like VSCode and Android Studio.
To enable them in your IDE, see <Link documentID="introduction/getting_started" hash="enabling-riverpod_lintcustom_lint" /> :::