0

我们有一个 GraphQL API,我们在其中使用 Relay 规范的基于光标的分页。在使用react-window-infinite-loader在无限滚动组件上做一些 UI 工作时,我们的开发人员注意到了一些情况,如果用户滚动得非常快,他们会很快从第 1 页转到第 20 页,而无需加载所有之间的页面。该loadMoreItems库中的函数具有以下签名:

(startIndex: number, stopIndex: number) => Promise<void>

他们首先使用 GraphQL Connection 类型中的 totalCount 的值填充 itemCount。

const itemCount = 1000;

<InfiniteLoader
  isItemLoaded={isItemLoaded}
  itemCount={itemCount}
  loadMoreItems={loadMoreItems}
>
  {({ onItemsRendered, ref }) => (
    <FixedSizeList
      itemCount={itemCount}
      onItemsRendered={onItemsRendered}
      ref={ref}
      {...otherListProps}
    />
  )}
</InfiniteLoader>

然后loadNextPage,他们不只是使用下面示例中的内容,而是考虑使用跳转到特定限制/偏移量的能力(如loadMoreItems上面的签名)而不是使用光标。

  // Are there more items to load?
  // (This information comes from the most recent API request.)
  hasNextPage,

  // Are we currently loading a page of items?
  // (This may be an in-flight flag in your Redux store for example.)
  isNextPageLoading,

  // Array of items loaded so far.
  items,

  // Callback function responsible for loading the next page of items.
  loadNextPage
}) {
  // If there are more items to be loaded then add an extra row to hold a loading indicator.
  const itemCount = hasNextPage ? items.length + 1 : items.length;

  // Only load 1 page of items at a time.
  // Pass an empty callback to InfiniteLoader in case it asks us to load more than once.
  const loadMoreItems = isNextPageLoading ? () => {} : loadNextPage;

  // Every row is loaded except for our loading indicator row.
  const isItemLoaded = index => !hasNextPage || index < items.length;

  // Render an item or a loading indicator.
  const Item = ({ index, style }) => {
    let content;
    if (!isItemLoaded(index)) {
      content = "Loading...";
    } else {
      content = items[index].name;
    }

    return <div style={style}>{content}</div>;
  };

  return (
    <InfiniteLoader
      isItemLoaded={isItemLoaded}
      itemCount={itemCount}
      loadMoreItems={loadMoreItems}
    >
      {({ onItemsRendered, ref }) => (
        <FixedSizeList
          itemCount={itemCount}
          onItemsRendered={onItemsRendered}
          ref={ref}
          {...props}
        >
          {Item}
        </FixedSizeList>
      )}
    </InfiniteLoader>
  );
}

我很好奇人们通常如何处理这样的情况。使用基于游标的分页的原因适用于我们的数据,因为它是动态的,并且可以在整个列表中删除或添加元素,因此肯定有机会仅使用限制/偏移来重复或跳过行。我们可以运行查询并仅返回带有 PageInfo 的连接,以获取所需偏移量的游标,而无需所有边,尽管这是一个额外的 http 请求。向 API 添加查询以获取给定索引的当前光标也可能是一种解决方案。尽管这两种解决方案似乎都不是很好。从基于光标的分页切换到限制/偏移听起来也不理想。我想知道在这种情况下常用的其他一些解决方案。

4

0 回答 0