fetchNextPage method

Future<List<TPage>?> fetchNextPage()

Fetches the subsequent page using nextPageParam and appends it to pages.

Automatically guarded against concurrent duplicate invocations: if a fetch is already in flight, returns the existing active Future.

if (feedQuery.hasNextPage.value) {
  await feedQuery.fetchNextPage();
}

Implementation

Future<List<TPage>?> fetchNextPage() async {
  if (_isDisposed) return null;
  if (_isFetchingNextPage.value) return _inFlightNextPage;
  if (!_hasNextPage.value || _nextPageParam == null) return null;

  final paramToFetch = _nextPageParam as TParam;
  _isFetchingNextPage.value = true;
  _isFetching.value = true;

  final nextPageKey = [...key, 'page', BloomData._canonical(paramToFetch)];

  final future = () async {
    try {
      final result = await BloomData.deduplicate<TPage>(
        nextPageKey,
        () => fetch(paramToFetch),
      );

      if (_isDisposed) return null;

      final currentPages = _data.value ?? <TPage>[];
      final newPages = [...currentPages, result];
      _pageParams.add(paramToFetch);
      _nextPageParam = getNextPageParam(result, newPages);

      BloomData.putEntry<List<TPage>>(
        QueryCacheEntry<List<TPage>>(
          key: key,
          data: newPages,
          updatedAt: DateTime.now(),
          staleTime: staleTime,
          cacheTime: cacheTime,
          isStale: false,
        ),
      );

      _data.value = newPages;
      _status.value = QueryStatus.success;
      _error.value = null;
      _isFetchingNextPage.value = false;
      _isFetching.value = false;
      _hasNextPage.value = _nextPageParam != null;
      _isStale.value = false;
      return newPages;
    } catch (err) {
      if (_isDisposed) return null;
      _error.value = err;
      _isFetchingNextPage.value = false;
      _isFetching.value = false;
      return null;
    } finally {
      _inFlightNextPage = null;
    }
  }();

  _inFlightNextPage = future;
  return future;
}