I created this StateNotifier with Riverpod in Flutter which Returns the Object DocumentsList
class TripStateNotifier extends StateNotifier<List<DocumentList>> {
TripStateNotifier() : super([]);
void getDocuments() async {
final res = await db.listDocuments(collectionId: '6286c0f1e7b7a5760baa');
state = res as List<DocumentList>;
}
}
final TripState = StateNotifierProvider((ref) => TripStateNotifier());
And this ConsumerWidget whicht gets the data
ref.watch(TripState)!.when(
data: (list) {
//Handeling if no data is found
if(list == null || (list.documents?.isEmpty ?? true)) return Center(child: Text("Yet you didn´t add any destinations to your trip", style: TextStyle(color: Colors.black.withOpacity(0.5)))); return ListView.builder(
itemCount: list.total,
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemBuilder: (context, index) {
return mytrip_card(
location: list.documents[index].data['location'], date: list.documents[index].data['date']
);
},
);
},
error: (e, s) => Text(e.toString()),
loading: () => const CircularProgressIndicator(),
),
My Problem is that my IDE Outputs following Error in regards to the when in ref.watch(TripState)!.when
The method 'when' isn't defined for the type 'Object'.
Intrestingly enought my Old Soulution with Future Provider worked why does this not?
Old solution:
final TripProvider = FutureProvider((ref)
async {
debugPrint('test');
final res = await db.listDocuments(collectionId: '6286c0f1e7b7a5760baa');
return res;
});
CodePudding user response:
Define StateNotifier
like this
final tripState = StateNotifierProvider<TripStateNotifier, List<DocumentList>>((ref) {
return TripStateNotifier();
});
Access to documents like this
List<DocumentList> trips = ref.watch(tripState);
return ListView.builder(
itemCount: trips.length,
itemBuilder: (context, index) {
...
}
);
See StateNotifierProvider for details.
CodePudding user response:
The method when
is only available for the object type AsyncValue
which can be provided by a FutureProvider
or a StreamProvider
.
Now that you are using a StateNotifierProvider
, you won't be able to use when
anymore, I would recommend you to create a "state" class to use with your TripStateNotifier
.
Code sample:
final tripStateProvider = StateNotifierProvider<TripStateNotifier, TripState>(
(ref) => TripStateNotifier());
class TripStateNotifier extends StateNotifier<TripState> {
TripStateNotifier() : super(const TripState());
void getDocuments() async {
// Trigger the loading state
state = state.copyWith(isLoading: true);
try {
final res = await db.listDocuments(collectionId: '6286c0f1e7b7a5760baa');
// Update the state with your newly fetched results
state = state.copyWith(
isLoading: false,
documents: res as List<DocumentList>,
);
} catch (e) {
// Manage received error
state = state.copyWith(
isLoading: false,
hasError: true,
);
}
}
}
@immutable
class TripState {
final bool isLoading;
final bool hasError;
final List<DocumentList> documents;
const TripState({
this.documents = const [],
this.isLoading = false,
this.hasError = false,
});
int get total => documents.length;
TripState copyWith({
List<DocumentList>? documents,
bool? isLoading,
bool? hasError,
}) {
return TripState(
documents: documents ?? this.documents,
isLoading: isLoading ?? this.isLoading,
hasError: hasError ?? this.hasError,
);
}
}
class MyWidget extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final currentState = ref.watch(tripStateProvider);
if (currentState.isLoading) return const CircularProgressIndicator();
if (currentState.documents.isEmpty) {
return Center(
child: Text(
"Yet you didn´t add any destinations to your trip",
style: TextStyle(
color: Colors.black.withOpacity(0.5),
),
),
);
}
return ListView.builder(
itemCount: currentState.total,
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemBuilder: (context, index) {
return MyTripCard(
location: currentState.documents[index].data['location'],
date: currentState.documents[index].data['date'],
);
},
);
}
}