You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hello I am trying to build an app that uses GraphQL with Blocs. I generated my graphql classes with the graphql_codegen. In this app a list of events (the 'History') is shown. A few items are loaded, and after this 'infinitive scroll' will execute the 'fetch more'. The backend can also create new items, which are retrieved by the app through subscriptions.
This all seems to work fine, until the following happens:
User opens page, history is loaded
Server pushes a new item through subscription
User closes page
User reopens page --> now the history is shown, but without the items pushed through subscription
It looks like calling the query function (again) directly returns the data from the cache, but the cache did not include the subscription data. Am I supposted to update the cache from both the subscriptions and fetchmore results manually through writeQuery? And if so, which variables do I need to provide to make sure that the normal query will pick up the changes?
Thanks in advance.
Dennis
class HistoryCubit extends Cubit<HistoryState> {
HistoryCubit(this._graphQLClient) : super(HistoryStateInitial());
final GraphQLClient _graphQLClient;
Future<void> loadAsync(String id) async {
try {
if (state is! HistoryStateLoading) {
emit(HistoryStateLoading());
await _stopSubscriptionAsync();
final subscription = _startSubscription(id);
final (result, history, hasReachedEnd) =
await _loadPlantHistoryAsync(id);
emit(HistoryStateLoaded(
id, history, hasReachedEnd, result, subscription));
}
} catch (ex) {
emit(HistoryStateError(ex));
}
}
Future<void> fetchMoreAsync() async {
if (state is HistoryStateLoaded) {
final loadedState = state as HistoryStateLoaded;
try {
emit(LoadedHistoryFetchingMoreState(
loadedState.id,
loadedState.history,
loadedState.hasReachedEnd,
loadedState.result,
loadedState.subscription,
));
await _fetchMore();
emit(HistoryStateLoaded(
loadedState.id,
loadedState.history,
loadedState.hasReachedEnd,
loadedState.result,
loadedState.subscription,
));
} catch (ex) {
// Ignoring: not a critical issue if fetching goes wrong
}
}
}
StreamSubscription<QueryResult<Subscription_historyAdded>> _startSubscription(
String id) {
final subscription = _graphQLClient
.subscribe_historyAdded(
Options_Subscription_historyAdded(
variables: Variables_Subscription_historyAdded(plantId: id),
),
)
.listen((event) {});
subscription.onData((data) {
if (data.parsedData?.addedHistory != null) {
final loadedState = state as HistoryStateLoaded;
loadedState.result.parsedData?.listHistory?.items?.insert(
0,
Mappr().convert<Subscription_historyAdded_addedHistory?, History?>(
data.parsedData?.addedHistory,
),
);
emit(
HistoryStateLoaded(
loadedState.id,
(loadedState.result.parsedData?.listHistory?.items?.nonNulls
.toList() ??
[]),
loadedState.hasReachedEnd,
loadedState.result,
loadedState.subscription,
),
);
}
});
subscription.onError((data) {
log("subscription onError: ${data.toString()}");
});
return subscription;
}
Future _stopSubscriptionAsync() async {
if (state is HistoryStateLoaded) {
final loadedState = state as HistoryStateLoaded;
await loadedState.subscription.cancel();
}
if (state is LoadedHistoryFetchingMoreState) {
final loadedState = state as HistoryStateLoaded;
await loadedState.subscription.cancel();
}
}
Future<
(
QueryResult<Query_listHistory> result,
List<History> history,
bool hasReachedEnd,
)> _loadPlantHistoryAsync(String id) async {
final result = await _graphQLClient.query_listHistory(
Options_Query_listHistory(
variables: Variables_Query_listHistory(
filter: Input_HistoryFilterInput(plantId: id),
),
),
);
return _processResult(result);
}
Future<void> _fetchMore() async {
if (state is HistoryStateLoaded) {
final loadedState = state as HistoryStateLoaded;
if (loadedState.hasReachedEnd != true) {
final options = FetchMoreOptions_Query_listHistory(
updateQuery: (previousResultData, fetchMoreResultData) {
final List<dynamic> historyItems = [
...previousResultData!['listHistory']['items'] as List<dynamic>,
...fetchMoreResultData!['listHistory']['items'] as List<dynamic>
];
fetchMoreResultData['listHistory']['items'] = historyItems;
return fetchMoreResultData;
},
variables: Variables_Query_listHistory(
nextToken: loadedState.result.parsedData?.listHistory?.nextToken,
));
final result = await _graphQLClient.fetchMore(options,
originalOptions: Options_Query_listHistory(
variables: Variables_Query_listHistory(
filter: Input_HistoryFilterInput(plantId: loadedState.id),
),
),
previousResult: loadedState.result);
_processResult(result);
}
}
}
(
QueryResult<Query_listHistory> result,
List<History> history,
bool hasReachedEnd,
) _processResult(QueryResult<Query_listHistory> result) {
return (
result,
result.parsedData?.listHistory?.items?.nonNulls.toList() ?? [],
result.parsedData?.listHistory?.isDone ?? false,
);
}
@override
Future<void> close() async {
await _stopSubscriptionAsync();
super.close();
}
}
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
Hello I am trying to build an app that uses GraphQL with Blocs. I generated my graphql classes with the graphql_codegen. In this app a list of events (the 'History') is shown. A few items are loaded, and after this 'infinitive scroll' will execute the 'fetch more'. The backend can also create new items, which are retrieved by the app through subscriptions.
This all seems to work fine, until the following happens:
It looks like calling the query function (again) directly returns the data from the cache, but the cache did not include the subscription data. Am I supposted to update the cache from both the subscriptions and fetchmore results manually through writeQuery? And if so, which variables do I need to provide to make sure that the normal query will pick up the changes?
Thanks in advance.
Dennis
Beta Was this translation helpful? Give feedback.
All reactions