react-infinite-scroll-component 使用注意事项

react-infinite-scroll-component 是一个非常实用的 React 组件,用来实现 无限滚动加载,常见的场景就是列表/卡片/瀑布流等下拉触底自动加载更多。


1. 安装

sql 复制代码
npm install react-infinite-scroll-component
# 或者
yarn add react-infinite-scroll-component

2. 基本使用

最简单的使用方法是包裹一个列表:

javascript 复制代码
import React, { useState } from "react";
import InfiniteScroll from "react-infinite-scroll-component";

export default function Demo() {
  const [items, setItems] = useState(Array.from({ length: 20 }));

  const fetchMoreData = () => {
    // 模拟异步请求
    setTimeout(() => {
      setItems((prev) => [
        ...prev,
        ...Array.from({ length: 20 }) // 追加 20 条数据
      ]);
    }, 1500);
  };

  return (
    <div>
      <h1>Infinite Scroll Example</h1>
      <InfiniteScroll
        dataLength={items.length} // 当前列表长度
        next={fetchMoreData} // 加载更多的方法
        hasMore={true} // 是否还有更多数据
        loader={<h4>加载中...</h4>} // 加载时的占位
        endMessage={<p style={{ textAlign: "center" }}>没有更多了 🎉</p>} // 没有数据时提示
      >
        {items.map((_, index) => (
          <div
            key={index}
            style={{
              height: 50,
              border: "1px solid #ccc",
              margin: 6,
              padding: 8
            }}
          >
            Item #{index}
          </div>
        ))}
      </InfiniteScroll>
    </div>
  );
}

3. 关键属性说明

  • dataLength

    当前列表的长度,必须正确设置,否则组件不会触发 next

  • next

    加载更多的方法(一般是异步请求接口)。

  • hasMore

    布尔值,表示是否还有更多数据。如果为 false,会显示 endMessage

  • loader

    加载时展示的内容,比如 loading...

  • endMessage

    当没有更多数据时显示的内容。

  • scrollableTarget

    如果滚动容器不是 window,需要设置一个 容器的 id

    ini 复制代码
    <div id="scrollableDiv" style={{ height: 400, overflow: "auto" }}>
      <InfiniteScroll
        dataLength={items.length}
        next={fetchMoreData}
        hasMore={true}
        loader={<h4>Loading...</h4>}
        scrollableTarget="scrollableDiv" // 指定容器
      >
        {/* 列表 */}
      </InfiniteScroll>
    </div>

4. 常见问题

  1. 为什么 next 不触发?

    • 一般是 dataLength 没有写对。
    • 或者外层容器高度不足,导致不触发滚动事件。
  2. 如何在接口没数据时停止加载?

    • 请求接口时判断是否还有数据,然后设置 hasMore = false
  3. 如果 第一次加载的数据太少,容器内容高度不够撑满滚动区域 ,那就根本滚不动,也就无法触发 next() 了。

方案 1:设置容器固定高度

给容器一个固定高度 + overflow: auto,这样即使数据很少,也会有一个可滚动的区域。

ini 复制代码
<div
  id="scrollableDiv"
  style={{
    height: 400,   // 固定高度
    overflow: "auto"
  }}
>
  <InfiniteScroll
    dataLength={items.length}
    next={fetchMoreData}
    hasMore={true}
    loader={<h4>Loading...</h4>}
    scrollableTarget="scrollableDiv"
  >
    {items.map((item, index) => (
      <div key={index}>{item}</div>
    ))}
  </InfiniteScroll>
</div>

方案 2:初始多加载几条

在首次请求时多拿一些数据(比如 20 条),保证能撑满容器。

  • 缺点:有时候数据量太大会影响首屏性能。
  • 适合内容较轻、接口响应快的场景。

方案 3:初始加载不足时,手动继续加载

你可以在 useEffect 里判断:如果内容高度 小于容器高度 ,那就直接调用一次 next(),直到撑满为止。

示例:

scss 复制代码
useEffect(() => {
  const container = document.getElementById("scrollableDiv");
  if (container && container.scrollHeight <= container.clientHeight) {
    fetchMoreData(); // 自动再拉一次数据
  }
}, [items]);

这样即使第一次数据少,也能自动补齐到能滚动。


方案 4:改用虚拟列表库

如果数据量特别大,不用 react-infinite-scroll-component,可以直接上 虚拟滚动库 (比如 react-windowreact-virtualized),它们能更好处理 小数据首屏 + 大数据无限加载 的问题。


总结:

  • 如果容器是 window:要么让首屏数据足够多,要么在首屏时主动拉几次数据。
  • 如果容器是 div:给定高度,配合 useEffect 判断不够高时自动加载。

与rc-virtual-list组件区别

1. react-infinite-scroll-component

🔹 核心功能无限滚动加载

  • 关注点是 什么时候触底,去触发 next() 请求更多数据
  • 它会把数据一条条 直接渲染到 DOM,不会做虚拟化
  • 每次都是真实 DOM 节点增加,数据越多 → DOM 越大 → 性能越差

适用场景

  • 数据量不算特别大(几百条以内)
  • 重点是"自动触发加载更多"逻辑
  • 列表项样式高度不固定也没问题

2. rc-virtual-list(虚拟列表)

🔹 核心功能虚拟化渲染

  • 关注点是 只渲染可视区的元素,不在屏幕上的元素直接移除
  • 对外表现是一个大列表,但实际 DOM 节点数只有几十个
  • 没有内置"无限加载"的功能(需要自己监听滚动 + 请求数据,再更新 list)
  • 对性能极好,数据量上万条也不卡

适用场景

  • 数据量非常大(成千上万条)
  • 对滚动性能要求高
  • 可结合分页/懒加载自己实现"无限加载"

3. 对比总结

特性 react-infinite-scroll-component rc-virtual-list
核心目标 无限加载 高性能虚拟渲染
滚动监听 内置 hasMore + next 需要自己处理
性能 大量数据时性能差(DOM 持续增加) 高性能(只渲染可视区)
使用复杂度 简单,拿来即用 稍复杂,需要自己结合分页加载
数据量适合 小到中等(几百到几千条) 超大数据量(几万甚至更多)
item 高度 自由(可不固定) 一般要求 item 高度固定或可计算

4. 如何选择?

  • 数据量小(几百条),要快速实现无限加载 👉 用 react-infinite-scroll-component
  • 数据量大(几千上万条),性能要求高 👉 用 rc-virtual-list(再手动实现无限加载逻辑)
  • 数据量中等,但既要无限加载又要虚拟化 👉 可以把 虚拟列表库无限加载逻辑 结合使用(比如在 rc-virtual-list 的 onScroll 里判断触底,触发加载)。
相关推荐
快乐是一切2 小时前
PDF文件的交叉引用表(xref)与 trailer
前端
emma羊羊2 小时前
【CSRF】防御
前端·网络安全·csrf
Paddy哥2 小时前
html调起exe程序
前端·html
emma羊羊2 小时前
【CSRF】跨站请求伪造
前端·网络安全·csrf
折翼的恶魔3 小时前
HTML基本标签二:
前端·html
我是日安3 小时前
零到一打造 Vue3 响应式系统 Day 16 - 性能处理:LinkPool
前端·vue.js
一树山茶3 小时前
uniapp的双token
前端·javascript
正义的大古3 小时前
OpenLayers地图交互 -- 章节六:范围交互详解
前端·javascript·vue.js·openlayers
訾博ZiBo3 小时前
【文本朗读小工具】- 快速、免费的智能语音合成工具
前端