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

React无限滚动组件首次加载正常,后续停滞于Loading状态求助

React无限滚动组件加载停滞问题排查与修复

问题现象

实现React无限滚动组件时,首次滚动至容器底部能正常加载新闻数据,但之后一直停留在“Loading...”状态,无法继续获取新的分页数据。

原代码片段

获取数据逻辑

const [latestNews, setLatestNews] = useState<any[]>([]);
const [page, setPage] = useState<number>(1);

const getLatestNews = async (page: number) => {
  let url = `https://api.nytimes.com/svc/search/v2/articlesearch.json?api-key=${API_KEY}&page=${page}`;
  
  const response = await fetch(url);
  const data = await response.json();
  setLatestNews(data.response.docs);
  setPage(page + 1);
}

无限滚动组件

<InfiniteScroll 
  dataLength={latestNews.length} 
  next={() => getLatestNews(page)} 
  hasMore={true} 
  loader={<h4>Loading...</h4>} 
  scrollableTarget="scrollableDiv"
>
  {
    latestNews.map((article, index) => (
      <div className="latest-news-article flex flex-col gap-3 mb-4" key={index}>
        <p className="latest-news-article-date">
          {article.pub_date.slice(11, 16)}
        </p>
        <h1>
          {article.headline.main}
        </h1>
      </div>
    ))
  }
</InfiniteScroll>

问题原因

  • 数据覆盖而非追加:setLatestNews(data.response.docs)直接替换了原数组,导致dataLength(即latestNews.length)在首次加载后没有增长,InfiniteScroll组件判断没有新数据加载完成,不会再次触发next回调。
  • 闭包导致page值固化:next={() => getLatestNews(page)}中的page是组件首次渲染时的闭包值,每次触发next都是传入page=1,后续请求始终获取第一页数据,无法真正翻页。

修复方案

1. 修改数据更新逻辑,追加新数据

将直接替换数组改为追加新数据,确保dataLength能正确反映列表总长度:

setLatestNews(prev => [...prev, ...data.response.docs]);

2. 解决page闭包问题

直接在getLatestNews中读取当前page状态,避免闭包带来的旧值问题:

const getLatestNews = async () => {
  const currentPage = page;
  let url = `https://api.nytimes.com/svc/search/v2/articlesearch.json?api-key=${API_KEY}&page=${currentPage}`;
  
  const response = await fetch(url);
  const data = await response.json();
  setLatestNews(prev => [...prev, ...data.response.docs]);
  setPage(prev => prev + 1);
}

// 对应InfiniteScroll的next修改为:
next={getLatestNews}

额外优化:添加加载状态与hasMore判断

避免重复请求和无效无限加载,可补充状态控制:

const [isLoading, setIsLoading] = useState(false);
const [hasMore, setHasMore] = useState(true);

const getLatestNews = async () => {
  if (isLoading) return;
  setIsLoading(true);
  
  try {
    const currentPage = page;
    let url = `https://api.nytimes.com/svc/search/v2/articlesearch.json?api-key=${API_KEY}&page=${currentPage}`;
    
    const response = await fetch(url);
    const data = await response.json();
    const newArticles = data.response.docs;
    
    setLatestNews(prev => [...prev, ...newArticles]);
    // 根据返回数据长度判断是否还有更多内容
    setHasMore(newArticles.length > 0);
    setPage(prev => prev + 1);
  } catch (error) {
    console.error('加载新闻失败:', error);
  } finally {
    setIsLoading(false);
  }
}

// 对应InfiniteScroll组件:
<InfiniteScroll 
  dataLength={latestNews.length} 
  next={getLatestNews} 
  hasMore={hasMore} 
  loader={<h4>Loading...</h4>} 
  scrollableTarget="scrollableDiv"
>
  {/* 渲染列表 */}
</InfiniteScroll>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 14:55:19