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

