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

React监听div滚动触底分页时同一次滚动触发多次API请求如何解决

问题核心原因
  1. React 原生 setState 方法不返回 Promise,你在代码中对 setState 使用 await 不会等待状态更新完成就会继续执行后续代码,导致profilesPaginating锁状态还没更新为true,高频触发的scroll事件就多次通过了校验,发起重复请求。
  2. scroll事件默认触发频率极高(每秒可达几十次),没有做节流处理的情况下,哪怕锁逻辑正常,也会产生大量无效判断,增加性能开销。
  3. 缺少请求错误处理逻辑,如果接口请求报错,profilesPaginating会一直保持为true,导致后续无法触发加载;同时没有无更多数据的终止判断,加载完全部数据后滑到底部仍会反复触发请求逻辑。
  4. 未在组件卸载时移除scroll事件监听,可能产生内存泄漏和异常触发。
修复方案

1. 封装异步setState

首先封装一个支持await的setState工具方法,确保状态更新完成后再执行后续逻辑:

// 新增方法
setStateAsync = (state: any) => {
  return new Promise(resolve => this.setState(state, resolve))
}

2. 给scroll事件添加节流+卸载时移除监听

修改生命周期逻辑,添加节流控制,避免高频触发,同时做好事件清理:

componentDidMount() {
  // 200ms内最多触发一次滚动监听,时长可根据实际需求调整
  this.throttledTrackScrolling = _.throttle(this.trackScrolling, 200)
  document.addEventListener('scroll', this.throttledTrackScrolling);
}

componentWillUnmount() {
  // 组件卸载时移除监听,清理节流函数
  document.removeEventListener('scroll', this.throttledTrackScrolling);
  this.throttledTrackScrolling.cancel()
}

如果不想引入lodash,也可以自己实现简单的节流逻辑。

3. 优化分页逻辑,添加错误处理和无数据终止判断

首先给state新增hasMoreProfiles字段,初始值设为true,修改paginateProfiles方法:

async paginateProfiles() {
  // 加载中或者没有更多数据时直接返回
  if (this.state.profilesPaginating || !this.state.hasMoreProfiles) {
    return;
  }

  // 用封装的异步setState保证锁状态生效后再发起请求
  await this.setStateAsync({
    profilesPaginating: true
  });

  try {
    const page = this.state.profilesNextPage;
    const response = await axios.get(process.env.REACT_APP_API_URL + '/profiles?amount=8&page=' + page)
    // 按单次请求返回8条的逻辑,返回长度不足8则代表没有更多数据,可根据实际接口规则调整
    const hasMore = response.data.length === 8;
    this.setState({
      profiles: this.state.profiles.concat(response.data),
      profilesNextPage: this.state.profilesNextPage + 1,
      profilesPaginating: false,
      hasMoreProfiles: hasMore
    });
  } catch (err) {
    // 请求失败时重置加载状态,避免卡住
    this.setState({
      profilesPaginating: false
    })
    console.error('列表加载失败:', err)
  }
}

4. 可选优化:isBottom添加提前加载偏移

可以给底部判断添加一定的偏移量,实现提前加载,提升用户体验,避免刚好卡到底部时判断反复横跳:

isBottom(el : any) {
  // 距离底部还有50px时就触发加载,数值可自行调整
  return el.getBoundingClientRect().bottom <= window.innerHeight + 50;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 10:15:03