
React 中无限滚动失效通常是因为 scroll 事件监听对象错误:若滚动发生在自定义容器(如带 overflow: scroll 的 div)内,必须监听该容器的 onScroll,而非 window 的 scroll 事件。
react 中无限滚动失效通常是因为 scroll 事件监听对象错误:若滚动发生在自定义容器(如带 `overflow: scroll` 的 div)内,必须监听该容器的 `onscroll`,而非 `window` 的 `scroll` 事件。
在你的代码中,<div className="results-page"> 被显式设置了 height: "100vh" 和 overflow: 'scroll',这意味着滚动行为实际发生在该 div 内部,而非整个浏览器窗口。因此,为 window 添加 scroll 事件监听器不会触发——因为 window 本身并未滚动(其 scrollTop 始终为 0),真正的滚动目标是这个 div 元素。
✅ 正确做法是:移除 useEffect 中对 window 的监听,改用 React 原生支持的 onScroll 属性直接绑定到滚动容器上。这不仅语义清晰、性能更优(无需手动管理事件生命周期),还能确保事件精准捕获容器的滚动状态。
以下是推荐实现方式:
const Demo = () => {
const handleInfiniteScrolling = (e: React.UIEvent<HTMLDivElement>) => {
const target = e.target as HTMLDivElement;
// 判断是否滚动到底部(常用阈值:剩余距离 ≤ 100px)
const isBottom =
target.scrollHeight - target.scrollTop - target.clientHeight <= 100;
if (isBottom) {
console.log("✅ 触发加载更多...");
// 这里调用 fetchMore() 或更新 loading 状态
}
// 调试信息(可选)
console.log({
scrollTop: target.scrollTop,
scrollHeight: target.scrollHeight,
clientHeight: target.clientHeight,
isBottom,
});
};
return (
<div
onScroll={handleInfiniteScrolling}
className="results-page"
style={{
height: "100vh",
overflowY: "auto", // 推荐使用 overflowY 显式控制
margin: 0, // 避免 body 默认边距干扰
}}
>
{data.map((item) => (
<MainLayer key={item._id} props={item} />
))}
</div>
);
};⚠️ 注意事项:
- 不要混用 window.addEventListener('scroll') 和容器内滚动:除非你明确监听的是视口滚动(如吸顶导航),否则对局部滚动容器应始终使用 onScroll。
- 避免重复绑定:onScroll 是声明式绑定,React 自动处理挂载/卸载,无需 useEffect + 手动 addEventListener。
- 样式兼容性:确保父容器(如 html, body)无默认 margin 或 padding,否则可能影响高度计算;建议重置基础样式(如 html, body { margin: 0; })。
- 防抖优化(进阶):高频滚动可能频繁触发,可在 handleInfiniteScrolling 内加入防抖逻辑(如 useRef 缓存 timer),避免重复请求。
总结:React 的无限滚动核心在于「监听谁在滚动」。定位准确的滚动容器,并使用 onScroll 直接响应,是最简洁、可靠且符合 React 设计哲学的实践方式。


















