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
相关产品推荐
相关产品推荐

