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

React无限滚动触发无限请求:Maximum update depth exceeded问题排查

解决MERN栈中react-infinite-scroller无限请求与更新深度超限问题

你遇到的无限API请求和Maximum update depth exceeded错误,核心源于两个关键问题:

  • hasMore条件逻辑错误:当前用posts.length < 10作为判断依据,只要帖子总数不足10,react-infinite-scroller会持续触发loadMore,哪怕用户没有滚动;且每次触发都会更新date状态,导致组件反复重渲染,形成循环。
  • 缺乏请求并发控制:API请求未完成时就发起新请求,加上状态频繁更新,让React陷入持续重渲染的死循环。

下面是具体的修复方案:


步骤1:添加状态控制

在Posts组件中新增两个状态,用于控制请求并发和加载终止:

const [date, setDate] = useState(startOfToday);
const [isLoadingMore, setIsLoadingMore] = useState(false); // 标记是否正在加载
const [hasMoreData, setHasMoreData] = useState(true); // 标记是否还有更多数据
const [prevPostsLength, setPrevPostsLength] = useState(0); // 跟踪上一次帖子总数

步骤2:修改getPosts函数,添加并发拦截

更新加载函数,确保只有在非加载状态且还有数据可加载时才发起请求:

const getPosts = async () => {
  // 阻止并发请求或无更多数据时的请求
  if (isLoadingMore || !hasMoreData) return;
  setIsLoadingMore(true);
  
  try {
    await getPostsByDate(date);
    // 更新日期为前一天
    const newDate = new Date(date);
    newDate.setDate(newDate.getDate() - 1);
    setDate(newDate);
  } catch (err) {
    console.error('加载更多失败:', err);
    setHasMoreData(false); // 请求出错时停止加载
  } finally {
    setIsLoadingMore(false); // 请求完成后重置加载状态
  }
};

步骤3:监听帖子变化,判断是否还有更多数据

添加useEffect监听posts状态,当新请求未返回任何帖子时,终止加载:

useEffect(() => {
  if (loading) return;
  // 如果帖子总数没有变化,说明最新请求未获取到数据
  if (posts.length === prevPostsLength) {
    setHasMoreData(false);
  }
  setPrevPostsLength(posts.length);
}, [posts, loading]);

步骤4:修正InfiniteScroll的hasMore属性

将hasMore改为结合加载状态和数据存在性的判断,避免无效触发:

<InfiniteScroll
  dataLength={posts.length}
  pageStart={0}
  loadMore={getPosts}
  hasMore={hasMoreData && !isLoadingMore}
  loader={
    <div className='loader' key={0}>
      Loading ...
    </div>
  }
>
  {/* 帖子渲染逻辑保持不变 */}
</InfiniteScroll>

额外优化(可选)

你可以修改后端API,返回包含数据和是否还有更多内容的对象,让前端判断更准确:

// 后端API修改示例
router.get('/:date', async (req, res) => {
  try {
    const startOfToday = new Date(req.params.date);
    const endOfToday = new Date(req.params.date);
    endOfToday.setDate(endOfToday.getDate() + 1);
    const posts = await Post.find({
      date: { $gte: startOfToday, $lte: endOfToday }
    }).sort({ date: -1 });
    // 返回是否还有更多数据(这里简单判断当前日期是否有帖子)
    res.json({ posts, hasMore: posts.length > 0 });
  } catch (err) {
    console.error(err.message);
    res.status(500).send('Server Error');
  }
});

同时修改action和组件逻辑,直接使用后端返回的hasMore值更新状态。


经过以上修改,你的组件会:

  • 仅在用户滚动到底部、无正在进行的请求且还有数据时发起新请求
  • 当某一天没有帖子返回时自动停止加载
  • 避免并发请求和无限重渲染循环

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:09:58