You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

react-window-infinite-loader预加载额外数据问题:页面加载时重复触发两次数据请求

解决InfiniteLoader初始触发两次请求及滚动过早加载的问题

我仔细看了你的代码,发现几个核心问题导致了当前的加载异常,下面逐一分析并给出修复方案:

1. 未正确利用isNextPageLoading阻止重复请求

你已经定义了loadMoreItems变量来处理"加载中不触发新请求"的逻辑,但在InfiniteLoader组件中传入的却是未做拦截的loadMoreItemsProxy,这就导致即使数据正在加载,仍然会触发新的请求,直接造成了初始两次请求的问题。

2. threshold值设置过大,触发过度预加载

你的List组件高度是150px,每个item高度30px,初始可见仅5个item。而设置的threshold=10意味着距离列表底部还有10个item时就触发加载,初始状态下数据量少,InfiniteLoader会直接预加载到"可见区域+threshold"的范围,进而连续触发两次加载请求。

3. 初始itemCount逻辑加剧加载触发

当初始items为空时,hasNextPage会因为0 % limit === 0判定为true,此时itemCount=0+1=1,InfiniteLoader会认为需要加载这个唯一的"加载指示器"项,触发第一次请求;加载完8条数据后,itemCount=8+1=9,结合threshold=10的设置,会再次触发加载请求第二页数据。


修复后的InfiniteList.js代码

import React from 'react';
import { FixedSizeList as List } from 'react-window';
import InfiniteLoader from 'react-window-infinite-loader';

export default function InfiniteList({ hasNextPage, isNextPageLoading, items, loadNextPage }) {
  // 如果还有更多数据要加载,则添加额外一行用于显示加载指示器
  const itemCount = hasNextPage ? items.length + 1 : items.length;

  const loadMoreItemsProxy = () => {
    // 按页加载的逻辑无需依赖start/end参数
    loadNextPage();
  };

  // 关键:正在加载时返回空Promise阻止新请求
  const loadMoreItems = isNextPageLoading ? () => Promise.resolve() : loadMoreItemsProxy;

  // 除加载指示器行外,所有行均已加载
  const isItemLoaded = (index) => !hasNextPage || index < items.length;

  // 渲染数据项或加载指示器
  const Item = ({ index, style }) => {
    let content;
    if (!isItemLoaded(index)) {
      content = 'Loading...';
    } else {
      content = items[index].courseFullName;
    }
    return <div style={style}>{content}</div>;
  };

  return (
    <InfiniteLoader
      isItemLoaded={isItemLoaded}
      itemCount={itemCount}
      loadMoreItems={loadMoreItems} // 替换为带加载拦截的函数
      minimumBatchSize={8}
      threshold={3} // 调整为和可见item数量相近的值,避免过早加载
    >
      {({ onItemsRendered, ref }) => (
        <List
          className="List"
          height={150}
          itemCount={itemCount}
          itemSize={30}
          onItemsRendered={onItemsRendered}
          ref={ref}
          width={300}
        >
          {Item}
        </List>
      )}
    </InfiniteLoader>
  );
}

额外优化建议

  • 强化请求幂等性:在redux的fetchNextPage逻辑中,确保isFetching为true时不再发起新请求,和前端的拦截形成双重保障。
  • 主动控制初始加载:可以在Training组件的componentDidMount中主动调用一次fetchNextPage,替代依赖InfiniteLoader的初始触发,逻辑更可控。
  • 动态调整threshold:如果列表高度或item高度可能变化,可以根据实际可见item数量动态计算threshold值,进一步优化加载时机。

内容的提问来源于stack exchange,提问作者Aakash Verma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 00:07:41