I am new to riverpod and while the articles have been helpful to get started I am struggling with stale state.
When a user logs in I am setting some state. When the details of the state change in DB I want the rebuild to happen automatically. While I am able to get a stream from the DB I am unable to connect the DB change to the riverpod state.
The pattern is for collaboration. Where two users are working on the same part of the application on independent phones, tablets etc.
I am using document stream and collection streams from firecloudstore.
Any helpful articles or how you have solved for this with riverpod? Do I have to invest time in learning something like BLoC for this?
You definitely don't need to learn BLoC to accomplish what you're after.
You say you're using firebase streams, so here's an example of live rebuilding when your data changes.
First, your repository layer.
class YourRepository {
YourRepository(this._read);
static final provider = Provider((ref) => YourRepository(ref.read));
final Reader _read;
Stream<YourModel?> streamById(String id) {
final stream = FirebaseFirestore.instance.collection('YourCollection').doc(id).snapshots();
return stream.map((event) => event.exists ? YourModel.fromJson(event.data()!) : null);
}
}
Next, define a StreamProvider that reads the stream defined in your repository.
final streamYourModelById = StreamProvider.autoDispose.family<YourModel?, String>((ref, id) {
return ref.watch(YourRepository.provider).streamById(id);
});
Last, use the StreamProvider in a widget to reload when your data changes.
// Hooks
class YourWidget extends HookWidget {
const YourWidget({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: useProvider(streamYourModelById('YourDataId')).when(
loading: () => const Center(child: CircularProgressIndicator()),
error: (err, stack) => Center(child: Text(err.toString())),
data: (yourData) => Center(child: Text(yourData?.toString() ?? 'Got Null')),
),
);
}
}
// Without Hooks
class YourWidget extends ConsumerWidget {
const YourWidget({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, ScopedReader watch) {
return Scaffold(
body: watch(streamYourModelById('YourDataId')).when(
loading: () => const Center(child: CircularProgressIndicator()),
error: (err, stack) => Center(child: Text(err.toString())),
data: (yourData) => Center(child: Text(yourData?.toString() ?? 'Got Null')),
),
);
}
}
You should be able to apply this pattern to accomplish whatever you need.