Skip to content

Extra blank gap after appending new items with infinite scroll #1847

@CavalcanteLeo

Description

@CavalcanteLeo

Current behavior

When using infinite scroll pagination, sometimes an extra blank space appears at the bottom of the list right after new items are appended.

This also happened for me on v1. I expected v2 to improve or fix it, but I still see the issue on @shopify/flash-list@^2.0.2.

Short screen recording attached.

Expected behavior

No blank gap at the end during or after pagination. The list should remain continuous as items are appended.

Screen.Recording.2025-08-23.at.00.30.36.mp4

I tried to add the whole code in a single component here:

  const renderItem = useCallback(
    ({ item, index }: { item: ApiFeedItem; index: number }) => {
      return <FeedCard item={item} index={index} />;
    },
    [],
  );


 return (
    <View className="flex-1 bg-gray-1000">
      <FlashList
        ref={listRef}
        data={data}
        keyExtractor={keyExtractor}
        renderItem={renderItem}
        getItemType={getItemType}
        keyboardDismissMode="interactive"
        showsHorizontalScrollIndicator={false}
        showsVerticalScrollIndicator={true}
        contentInset={{
          top: liveHeaderHeight + paddingTop,
          bottom: tabBarHeight + keyboardHeight + paddingTop,
        }}
        contentOffset={{
          x: 0,
          y: -(liveHeaderHeight + paddingTop),
        }}
        scrollIndicatorInsets={{
          top: liveHeaderHeight,
          bottom: tabBarHeight + keyboardHeight,
        }}
        automaticallyAdjustContentInsets={false}
        contentInsetAdjustmentBehavior="never"
        automaticallyAdjustsScrollIndicatorInsets={false}
        automaticallyAdjustKeyboardInsets={false}
        drawDistance={2000}
        scrollEventThrottle={64}
        removeClippedSubviews={true}
        onEndReached={handleEndReached}
        onEndReachedThreshold={0.8}
        ItemSeparatorComponent={() => (
          <View className="flex-1 py-4 pl-4 bg-gray-1000">
            <View className="h-px w-full bg-gray-900" />
          </View>
        )}
        viewabilityConfig={{
          minimumViewTime: 100,
          viewAreaCoveragePercentThreshold: 50,
        }}

        onViewableItemsChanged={handleViewableItemsChanged} // this just handles analytics

        ListHeaderComponent={() => (
          <View className="pt-2">
            {/* Upload Progress */}
            <UploadProgressList showTitle={false} maxHeight={200} />

            {/* Reset filters */}
            <AppliedFiltersHeader onReset={handleResetFilters} />

            {/* Timezone disclaimer */}
            <TimezoneDisclaimer />

            {/* Stale data disclaimer */}
            <StaleDataDisclaimer
              dataUpdatedAt={dataUpdatedAt}
              onRefresh={handleRefresh}
              isRefreshing={isRefreshing}
            />
          </View>
        )}
        refreshControl={
          <RefreshControl
            refreshing={isRefreshing}
            onRefresh={handleRefresh}
            tintColor="white"
            titleColor="white"
          />
        }
        ListFooterComponent={() => {
          const showLoading = hasNextPage && !paginationError;
          const showError = paginationError !== null;
          const hasReachedEnd = !hasNextPage && !showError && data.length > 0;

          if (showLoading) {
            return (
              <View className="bg-gray-1000 items-center justify-center py-8">
                <ActivityIndicator size="large" color="white" />
                <BondiText className="text-gray-400 mt-3">
                  {isFetchingNextPage || isLoadingMore
                    ? 'Loading more...'
                    : 'Loading next page...'}
                </BondiText>
              </View>
            );
          }

          if (showError) {
            return (
              <View className="bg-gray-1000 items-center justify-center py-8 px-6">
                <BondiText className="text-red-400 text-center mb-2">
                  Failed to load more items
                </BondiText>
                <BondiText className="text-gray-400 text-center mb-4 text-sm">
                  {paginationError}
                </BondiText>
                <BondiText
                  className="text-primary text-base px-4 py-2 bg-gray-900 rounded-lg"
                  onPress={handleRetryPagination}
                >
                  Tap to retry
                </BondiText>
              </View>
            );
          }

          if (hasReachedEnd) {
            return (
              <View className="bg-gray-1000 py-12 px-6">
                <View className="h-px w-full px-10  bg-gray-900 mt-6 mb-12" />
                <View className="relative bg-gray-1000 items-center justify-center ">
                  <BondiText className="text-white text-lg font-semibold mb-2 text-center">
                    That's all for now, party animal!
                  </BondiText>
                  <BondiText className="text-gray-400 text-center leading-5">
                    You've seen all the hottest spots in town. Time to get off
                    your phone and hit the dance floor!
                  </BondiText>
                  <BondiText className="text-gray-500 text-sm mt-4 text-center">
                    Pull down to refresh for the latest updates
                  </BondiText>
                </View>
              </View>
            );
          }

          return null;
        }}
      />
    </View>
  );

Notes:

  • The gap is intermittent and often appears right after new items are appended.

Platform:

  • iOS
  • Android

Environment

  • @shopify/flash-list: ^2.0.2

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1Important but not urgentbugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions