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

React中onScroll事件未触发,无限滚动功能实现遇阻求助

React无限滚动onScroll事件不触发的排查与修复

核心问题拆解

  • 目标滚动元素不存在:你在useEffect里尝试获取id="scroll_div"的元素,但返回的JSX中没有任何元素设置该id,导致document.getElementById("scroll_div")返回null,无法绑定scroll事件。
  • 滚动容器无固定高度:MUI的Box设置了overflow: auto,但如果没有固定高度(如height: 100vh),容器会自适应内容高度,不会出现滚动条,自然无法触发onScroll。
  • 数据更新逻辑错误:fetchPosts中直接用setData(newPosts)替换原有数据,而非追加,会覆盖之前的帖子,不符合无限滚动的预期。
  • 事件绑定冗余:同时在Box上设置onScroll={handleScroll}和手动绑定DOM事件,属于重复操作,且后者因元素不存在完全失效。

修复后的完整代码

import { Box } from "@mui/material";
import Post from "./Post";
import About from "./About";
import { useEffect, useState } from "react";
import { getInfiniteScroll } from "../apis/posts";

const Feed = () => {
  const [data, setData] = useState([]);
  const [skip, setSkip] = useState(0);
  const [isLoading, setIsLoading] = useState(false); // 防止重复请求

  useEffect(() => {
    fetchPosts();
  }, [skip]);

  const fetchPosts = async () => {
    if (isLoading) return;
    setIsLoading(true);
    try {
      const newPosts = await getInfiniteScroll(skip);
      setData(prev => [...prev, ...newPosts]); // 追加新数据而非替换
    } catch (error) {
      console.log(error.message);
    } finally {
      setIsLoading(false);
    }
  };

  const handleScroll = (e) => {
    const { offsetHeight, scrollTop, scrollHeight } = e.target;
    // 滚动接近底部时触发加载,增加小偏移量避免边界误判
    if (offsetHeight + scrollTop >= scrollHeight - 10 && !isLoading) {
      // 建议用固定每页条数更新skip,比如每页10条,避免闭包导致的旧值问题
      setSkip(prev => prev + 10);
      // 如果接口依赖data.length,可改为setSkip(data.length),但需注意异步更新延迟
    }
  };

  return (
    <Box
      flex={4}
      sx={{ 
        padding: { xs: "0", sm: "0px 20px " }, 
        overflow: "auto",
        height: "100vh", // 设置固定高度,让容器出现滚动条
        maxHeight: "100vh"
      }}
      onScroll={handleScroll}
    >
      <Post post={data} />
      {isLoading && <div>加载中...</div>} {/* 显示加载状态 */}
      <Box
        sx={{
          display: { sm: "none", xs: "block" },
          justifyContent: "center",
          alignItems: "center",
          paddingBottom: "50px",
        }}>
        <About />
      </Box>
    </Box>
  );
};

export default Feed;

关键修复说明

  1. 添加固定高度:给滚动容器设置height: 100vh,确保内容超过容器高度时出现滚动条,触发onScroll事件。
  2. 修正数据追加逻辑:使用setData(prev => [...prev, ...newPosts])保留原有帖子,实现滚动加载的累加效果。
  3. 移除无效DOM操作:直接使用React的onScroll props绑定事件,无需手动操作DOM,避免元素不存在的错误。
  4. 新增加载状态:防止滚动到底部时重复触发API请求,避免接口压力和数据重复。
  5. 优化skip更新:使用函数式更新setSkip(prev => prev + 10),避免闭包导致的旧值问题(若接口依赖data.length,可替换为setSkip(data.length))。

内容的提问来源于stack exchange,提问作者Shiv Shankar Prasad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 02:05:32