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

React滚动动态分页:距离底部250px时一次性加载全部数据问题排查

异常成因
  • setState异步更新问题:scroll事件触发频率极高,当满足距离底部≤250px的条件时,首次触发逻辑后调用的setState不会立即更新isFetching和currentItem的值,后续连续触发的scroll事件读取到的还是更新前的isFetching=false状态,会重复执行加载逻辑,连续给currentItem累加10。
  • 阈值特性差异:阈值为0时,加载新数据后页面高度增加,滚动位置会自动脱离≤0的条件,不会重复触发;但阈值为250px时,新数据渲染后当前滚动位置大概率仍满足≤250px的条件,会持续触发加载逻辑。
  • 判断条件遗漏:scrollHandler的触发判断没有加入isFetching状态校验,即使已经处于加载流程中,只要满足距离和总量条件就会重复触发逻辑。
  • 代码隐含bug:原有代码中合并数组的写法有误,{...this.state.data, ...result.data}是将数组作为对象展开,会导致数据结构异常。
修复方案
  1. 调整scrollHandler的判断条件,加入!this.state.isFetching的校验,只有当前未处于加载状态时才触发新的加载
  2. 改用函数式setState更新依赖前序状态的变量,避免异步更新导致的取值错误
  3. 修正数组合并的写法,正确拼接新老数据

修复后完整代码如下:

import React, { Component } from 'react';

class Orders extends Component {
  constructor(props) {
    super(props);
    this.state = {
      data: [],
      isFetching: true,
      currentItem: 0,
      totalLoading: 0,
      totalCount: 33
    };
  }

  loadingData() {
    if (this.state.isFetching) {
      fetch('/api/orders', {
        method: 'POST',
        headers: {
          Accept: 'application/json',
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ 'limit': 10, 'item': this.state.currentItem }),
      })
        .then(response => response.json())
        .then(result => {
          this.setState(prevState => ({
            data: [...prevState.data, ...result.data],
            totalLoading: prevState.totalLoading + result.data.length
          }));
        })
        .finally(() => this.setState({ isFetching: false }));
    }
  }

  scrollHadler = () => {
    const distanceToBottom = document.documentElement.scrollHeight - (document.documentElement.scrollTop + window.innerHeight);
    // 加入isFetching判断,避免重复触发
    if (distanceToBottom <= 250 && !this.state.isFetching && this.state.totalLoading < this.state.totalCount) {
      this.setState(prevState => ({
        isFetching: true,
        currentItem: prevState.currentItem + 10
      }), () => {
        // 等state更新完成后再调用加载方法,确保参数正确
        this.loadingData();
      });
    }
  }

  componentDidMount() {
    this.loadingData();
    document.addEventListener('scroll', this.scrollHadler);
  }

  componentWillUnmount() {
    document.removeEventListener('scroll', this.scrollHadler);
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 20:54:02