React无限滚动组件问题:next自动多次调用API求助
React无限滚动中API被多次调用的问题排查与修复
问题核心原因
你的代码里有几个关键问题导致API被重复调用:
useCallback依赖了responseData,每次数据更新都会重建fetchData函数,触发useEffect再次调用API- 没有加载状态控制,滚动时会连续触发
next回调 hasMore始终设为true,不会停止后续请求- 状态更新用了
responseData.concat而非函数式写法,容易导致数据合并错误,同时加重依赖问题
修复步骤及代码修改
1. 添加加载状态,阻止并行请求
先新增一个状态来标记是否正在加载,避免同一时间发起多个API请求:
const [isLoading, setIsLoading] = useState(false);
2. 重构fetchData函数
修改fetchData,移除不必要的依赖,用函数式更新状态,同时添加加载状态控制:
const fetchData = useCallback(async () => { // 正在加载或已到最后一页时,直接返回 if (isLoading || page > totalPage) return; setIsLoading(true); try { const response = await axios.get(`http://sampleURL/api/?page=${page}`); // 用函数式更新获取最新的state,避免依赖responseData setresponseData(prev => [...prev, ...response.data.users.data]); setTotalLength(response.data.users.total); setTotalPage(response.data.users.last_page); // 同样用函数式更新page setPage(prev => prev + 1); } catch (error) { console.error('加载数据失败:', error); } finally { setIsLoading(false); } }, [page, totalPage, isLoading]);
3. 修正初始加载的useEffect
初始加载只需要触发一次,不需要依赖fetchData:
useEffect(() => { fetchData(); }, []);
4. 调整InfiniteScroll组件参数
dataLength改为已加载的数据长度(responseData.length),组件需要根据这个值判断何时触发下一页hasMore根据当前页和总页数、加载状态动态判断:
<InfiniteScroll dataLength={responseData.length} next={fetchData} hasMore={page <= totalPage && !isLoading} scrollableTarget="scrollableDiv" loader={<div className="text-center py-4">加载中...</div>} > <ResponseList responseData={responseData}/> </InfiniteScroll>
关键修改说明
- 加载状态
isLoading:彻底避免滚动时连续触发next导致的重复API请求 - 函数式状态更新:不再依赖
responseData,防止useCallback频繁重建,同时保证状态更新的准确性 - 正确的
hasMore判断:当已加载到最后一页或者正在加载时,停止触发后续请求 dataLength修正:react-infinite-scroll-component的dataLength是用来计算滚动位置的,必须传入已加载的数据长度,而非总数据量
内容的提问来源于stack exchange,提问作者Dirty Rex
相关产品推荐
相关产品推荐

