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

FlatList onEndReached无限循环及重复调用问题求助

解决FlatList的重复请求与无限循环问题

我来帮你搞定这两个FlatList的常见头疼问题!咱们一步步分析和解决:

问题1:滚动到底部时两次触发_fetchData

原因

  • 你的onEndReachedThreshold设为了0.5,意味着列表滚动到距离底部还有一半屏幕高度时就会触发回调,加上FlatList在状态更新(比如你设置showLoadingBottom: true)后会重新计算滚动位置,容易导致重复触发。
  • 缺少请求状态拦截:第一次_fetchData还在进行时,滚动动作可能再次触发回调,没有阻止重复请求的逻辑。

解决方法

  1. 调小onEndReachedThreshold,比如设为0.1(距离底部10%高度时触发,更符合常规下拉加载的预期)。
  2. 利用isFetching状态做拦截:触发_fetchData前先判断是否正在请求,避免重复触发。

问题2:无更多数据时onEndReached无限循环

原因

你没有标记“是否还有更多数据”的状态,即使服务器返回空数据,FlatList只要滚动到底部附近,还是会不断触发onEndReached回调——它根本不知道已经没有数据可加载了。

解决方法

  1. 在state中新增hasMore字段,用来标记是否还有更多数据可加载。
  2. 在_fetchData请求完成后,根据服务器返回的数据判断是否还有更多(比如返回的数据长度小于每页请求数量,就说明没有更多了)。
  3. 在onEndReached回调中,增加hasMore和isFetching的双重判断,只有当有更多数据且不在请求中时,才触发加载。

修改后的完整代码示例

更新State

state = { 
  refresh: true, 
  isFetching: true, 
  showLoadingBottom: false, 
  data: [],
  hasMore: true // 新增:标记是否还有更多数据
};

修改_fetchData函数(增加状态控制与hasMore判断)

_fetchData = async () => {
  // 拦截:正在请求或无更多数据时直接返回
  if (this.state.isFetching || !this.state.hasMore) return;

  try {
    this.setState({ isFetching: true });
    // 替换成你的实际请求逻辑
    const response = await fetch('你的接口地址');
    const newData = await response.json();

    // 判断是否还有更多数据:假设每页请求10条,返回不足10条则无更多
    const hasMore = newData.length === 10;

    this.setState(prevState => ({
      data: prevState.refresh ? newData : [...prevState.data, ...newData],
      refresh: false,
      isFetching: false,
      showLoadingBottom: false,
      hasMore
    }));
  } catch (error) {
    console.error('请求失败:', error);
    this.setState({
      isFetching: false,
      showLoadingBottom: false
    });
  }
};

修改render中的FlatList部分

render() {
  return (
    <View style={{ flex: 1 }}>
      <FlatList
        refreshControl={
          <RefreshControl
            refreshing={this.state.refresh}
            onRefresh={() => {
              // 下拉刷新时重置hasMore,确保能重新加载所有数据
              this.setState({ refresh: true, hasMore: true }, this._fetchData);
            }}
            title={"Pull To Refresh"}
            tintColor={darkGrey}
            titleColor={darkGrey}
          />
        }
        onEndReachedThreshold={0.1} // 调小阈值减少误触发
        onEndReached={() => {
          // 只有满足条件才触发加载
          if (!this.state.isFetching && this.state.hasMore) {
            this.setState({ showLoadingBottom: true }, this._fetchData);
          }
        }}
        showsVerticalScrollIndicator={false}
        data={this.state.data}
        ListFooterComponent={() => {
          return (
            this.state.showLoadingBottom && (
              <View style={{ padding: 10 }}>
                <ActivityIndicator size="small" color={colorAccent} />
              </View>
            )
          );
        }}
        renderItem={this._renderItem}
        keyExtractor={(item) => item.id.toString()}
        removeClippedSubviews={true}
      />
    </View>
  );
}

额外提醒

  • isFetching状态一定要在请求开始时设为true,请求结束(成功/失败)时设为false,这是阻止重复请求的核心。
  • 下拉刷新时记得重置hasMore为true,否则用户刷新后可能无法加载新的分页数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:10:43