How to Use Riverpod in Flutter: Simple Guide with Examples
To use
Riverpod in Flutter, first add the flutter_riverpod package, then create providers to manage state and consume them in widgets using ConsumerWidget or hooks. Riverpod offers a simple, safe way to manage app state without context dependencies.Syntax
Riverpod uses providers to expose state or objects. You define a provider, then read or watch it inside widgets.
final myProvider = Provider<Type>((ref) => value);defines a provider.ConsumerWidgetorConsumerwidgets listen to providers.ref.watch(myProvider)reads the current value reactively.
dart
import 'package:flutter_riverpod/flutter_riverpod.dart'; final greetingProvider = Provider<String>((ref) { return 'Hello Riverpod!'; }); class MyWidget extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final greeting = ref.watch(greetingProvider); return Text(greeting); } }
Output
A Text widget displaying: Hello Riverpod!
Example
This example shows a counter app using Riverpod to manage the counter state. It demonstrates defining a StateProvider, reading and updating state inside a ConsumerWidget.
dart
import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; final counterProvider = StateProvider<int>((ref) => 0); void main() { runApp(ProviderScope(child: MyApp())); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp(home: CounterScreen()); } } class CounterScreen extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final count = ref.watch(counterProvider); return Scaffold( appBar: AppBar(title: Text('Riverpod Counter')), body: Center(child: Text('Count: $count', style: TextStyle(fontSize: 24))), floatingActionButton: FloatingActionButton( onPressed: () => ref.read(counterProvider.notifier).state++, child: Icon(Icons.add), ), ); } }
Output
App screen with text 'Count: 0' and a button; pressing button increments count displayed.
Common Pitfalls
Common mistakes when using Riverpod include:
- Not wrapping the app with
ProviderScope, which is required to use providers. - Using
ref.readinstead ofref.watchinsidebuildmethods, which prevents UI updates. - Mutating state directly instead of using the provider's state setter.
dart
/* Wrong: Not wrapping app with ProviderScope */ void main() { runApp(MyApp()); // Missing ProviderScope } /* Correct: Wrap with ProviderScope */ void main() { runApp(ProviderScope(child: MyApp())); } /* Wrong: Using ref.read in build to watch state */ final count = ref.read(counterProvider); // Won't update UI /* Correct: Use ref.watch to rebuild on changes */ final count = ref.watch(counterProvider);
Quick Reference
Here is a quick summary of common Riverpod providers and usage:
| Provider Type | Purpose | Example |
|---|---|---|
| Provider | Expose a value or object | final greeting = Provider((ref) => 'Hi'); |
| StateProvider | Manage simple mutable state | final counter = StateProvider((ref) => 0); |
| FutureProvider | Async data from a Future | final data = FutureProvider((ref) => fetchData()); |
| StreamProvider | Async data from a Stream | final stream = StreamProvider((ref) => streamData()); |
Key Takeaways
Always wrap your Flutter app with ProviderScope to enable Riverpod.
Define providers to hold state or objects and consume them with ref.watch inside ConsumerWidget.
Use StateProvider for simple mutable state and update it via ref.read(provider.notifier).state.
Avoid using ref.read inside build methods when you want UI to update on state changes.
Riverpod provides a safe, testable, and context-independent way to manage state in Flutter.