Skip to content

Merge Pagination Data

Problem

You need to implement load more functionality that merges new paginated data with existing cached results without duplicates.

The datasource provides a loadMore method that uses updateResult for merging:

class HotelBookingsDatasource {
@override
void loadMore({
required int skip,
required int take,
GhotelbookingsFilters? filter,
GhotelbookingsOrder? sort,
}) {
final listHolder = requestContext.getHolder<GQueryHotelBookingsReq>(
HotelBookingsRequestStrategyKeys.hotelBookingsList.name,
);
final params =
ListRequestParams<GhotelbookingsFilters, GhotelbookingsOrder>(
skip: skip,
take: take,
filter: filter,
sort: sort,
);
final nextRequest =
listHolder?.request?.rebuild(
(b) => b
..vars.G_skip = skip
..updateResult = (previous, result) {
if (previous == null) return result;
return previous.rebuild(
(b) => b
..hotelbookings.hotelbookingsItems.addAll(
result?.hotelbookings?.hotelbookingsItems?.toList() ?? [],
),
);
},
) ??
requestContext.execute<
GQueryHotelBookingsReq,
ListRequestParams<GhotelbookingsFilters, GhotelbookingsOrder>
>(HotelBookingsRequestStrategyKeys.hotelBookingsList.name, params);
client.requestController.add(nextRequest);
}
}

The key to pagination merging is the updateResult function that combines previous and new data:

  1. Request Holder - Get the existing request to rebuild it
  2. Skip Update - Update the skip parameter for the next page
  3. UpdateResult Function - Merge previous data with new results
  4. Request Controller - Add the rebuilt request to the queue
..updateResult = (previous, result) {
if (previous == null) return result;
return previous.rebuild(
(b) => b
..hotelbookings.hotelbookingsItems.addAll(
result?.hotelbookings?.hotelbookingsItems?.toList() ?? [],
),
);
}

This function:

  • Returns new result if no previous data exists
  • Rebuilds previous data by adding new items to the existing list
  • Handles null safety with the ?? [] operator

For scenarios requiring duplicate prevention, enhance the updateResult function:

..updateResult = (previous, result) {
if (previous == null) return result;
final existingItems = previous.hotelbookings?.hotelbookingsItems?.toList() ?? [];
final newItems = result?.hotelbookings?.hotelbookingsItems?.toList() ?? [];
final existingIds = existingItems
.where((item) => item?.id != null)
.map((item) => item!.id!)
.toSet();
final uniqueNewItems = newItems
.where((item) => item?.id != null && !existingIds.contains(item!.id!))
.toList();
return previous.rebuild(
(b) => b
..hotelbookings.hotelbookingsItems.addAll(uniqueNewItems)
..hotelbookings.totalCount = result?.hotelbookings?.totalCount,
);
}
## Repository Load More
The repository exposes the load more functionality:
```dart
class HotelBookingsRepository {
@override
void loadMore({
required int skip,
required int take,
HotelBookingFilterCriteria? filter,
HotelBookingSortCriteria? sort,
}) {
datasource.loadMore(
skip: skip,
take: take,
filter: filter?.toGql,
sort: sort?.toGql,
);
}
}