I have an archaic solution for my problem, but it's quickly become cumbersome and not as robust. I want to switch to a riverpod provider and am studying how to do so, but I want to put this question out there at the same time. For simplicity, my app is similar to BlaBlaCar. Lots of trips listed, and then users can request to be picked up. The general flow goes like this:
To call the same document ID from Firestore, my solution has been just to pass a detailDocument parameter over and over. In my trips page, I have a streambuilder that displays the document:
StreamBuilder<QuerySnapshot<Object?>> tripStreamBuilder() {
return StreamBuilder<QuerySnapshot>(
stream: tripStream.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return const Center(child: CircularProgressIndicator());
}
if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
}
return ListView(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
children: snapshot.data!.docs.map((DocumentSnapshot document) {
Map<String, dynamic> data =
document.data()! as Map<String, dynamic>;
return Card(
child: ListTile(
// leading: Text((data['departureDate']).toString()),
title: Text('From ${data['departure']}'),
subtitle: Text('To ${data['arrival']}'),
trailing: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Text((data['departureDate']).toString()),
Text('Leaving at ${data['departureTime']}'),
],
),
),
onTap: () {
Navigator.of(context, rootNavigator: true)
.push(MaterialPageRoute(
builder: (context) => TripDetails(
detailDocument: document,
)));
},
),
);
}).toList(),
);
},
);
From here, I just keep making detailDocument a parameter. For exmaple in my trip details:
class TripDetails extends ConsumerStatefulWidget {
const TripDetails({super.key, required this.detailDocument});
final DocumentSnapshot detailDocument;
And jointrip class:
class JoinTrip extends ConsumerStatefulWidget {
const JoinTrip({
super.key,
required this.detailDocument,
});
final DocumentSnapshot detailDocument;
So my question is how can I pass the document ID into a riverpod provider? And one that gets disposed and reset as users click on different trips.
You shouldn't pass the id
of your document to pages. You can check this example from the official documentation.
In you case, you can have a provider that saves the id
. So whenever you need to fetch or do something about the same id, you watch its value and when you need to change it, you can change the id in that provider.
Let's say we have two providers as follow:
// id provider
final tripIdProvider = StateProvider<String?>((ref) => null);
// Another provider fetching the document for an id
final tripProvider = Provider((ref) {
final id = ref.watch(tripIdProvider);
// code to call the Firebase and returning the result for instance.
});
tripIdProvider
has the latest clicked id
, and tripProvider
will watch this id
and updates and fetch the new values if the id
changes. It fetches the document of that id from the Firebase.
Now if user clicks another object having another id, in the callback of pressing/tapping that object, you can do something like this:
...
onPressed:(){
ref.read(tripIdProvider.notifier).state = id;
}
This will change the id
and because tripProvider
is watch
ing that providers' value, it will be triggered again and will fetch new data for the new id
.
It's also good to check stateNotifier.