当前位置:首页 > React

react实现分页滚动加载

2026-01-27 13:28:00React

实现分页滚动加载的基本思路

分页滚动加载(无限滚动)的核心逻辑是监听滚动事件,当用户滚动到接近页面底部时触发数据加载。React中可以通过结合useEffect和DOM事件监听实现。

监听滚动事件并触发加载

在React组件中,通过useEffect添加滚动事件监听器,计算是否到达页面底部:

useEffect(() => {
  const handleScroll = () => {
    const { scrollTop, clientHeight, scrollHeight } = document.documentElement;
    if (scrollTop + clientHeight >= scrollHeight - 10) {
      loadMoreData();
    }
  };

  window.addEventListener('scroll', handleScroll);
  return () => window.removeEventListener('scroll', handleScroll);
}, []);

数据加载逻辑

实现异步加载数据的函数,通常需要维护当前页码和加载状态:

const [data, setData] = useState([]);
const [page, setPage] = useState(1);
const [loading, setLoading] = useState(false);

const loadMoreData = async () => {
  if (loading) return;

  setLoading(true);
  try {
    const newData = await fetchData(page); // 替换为实际API调用
    setData(prev => [...prev, ...newData]);
    setPage(prev => prev + 1);
  } finally {
    setLoading(false);
  }
};

优化性能与体验

使用Intersection Observer API替代传统滚动监听,性能更好:

useEffect(() => {
  const observer = new IntersectionObserver(
    (entries) => {
      if (entries[0].isIntersecting) {
        loadMoreData();
      }
    },
    { threshold: 1.0 }
  );

  if (loaderRef.current) {
    observer.observe(loaderRef.current);
  }

  return () => observer.disconnect();
}, [loading]);

在页面底部添加一个哨兵元素作为观察节点:

<div ref={loaderRef}>
  {loading && <p>Loading more data...</p>}
</div>

完整组件示例

import React, { useState, useEffect, useRef } from 'react';

function InfiniteScrollList() {
  const [items, setItems] = useState([]);
  const [page, setPage] = useState(1);
  const [loading, setLoading] = useState(false);
  const loaderRef = useRef(null);

  const fetchItems = async (pageNum) => {
    // 模拟API请求
    return new Array(10).fill(0).map((_, i) => 
      `Item ${(pageNum - 1) * 10 + i + 1}`
    );
  };

  const loadMore = async () => {
    if (loading) return;
    setLoading(true);
    try {
      const newItems = await fetchItems(page);
      setItems(prev => [...prev, ...newItems]);
      setPage(prev => prev + 1);
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    const observer = new IntersectionObserver(
      (entries) => {
        if (entries[0].isIntersecting) {
          loadMore();
        }
      },
      { threshold: 1.0 }
    );

    if (loaderRef.current) {
      observer.observe(loaderRef.current);
    }

    return () => observer.disconnect();
  }, [loading]);

  return (
    <div>
      {items.map((item, index) => (
        <div key={index} style={{ padding: '20px', border: '1px solid #ccc' }}>
          {item}
        </div>
      ))}
      <div ref={loaderRef}>
        {loading && <p>Loading...</p>}
      </div>
    </div>
  );
}

export default InfiniteScrollList;

注意事项

  • 添加防抖逻辑避免频繁触发加载
  • 处理API请求错误情况
  • 在组件卸载时清除事件监听器
  • 考虑移动端兼容性
  • 实现数据加载完毕后的终止逻辑(无更多数据时)

使用现成库的方案

如需快速实现,可以考虑使用现成的React无限滚动库:

npm install react-infinite-scroll-component

示例用法:

import InfiniteScroll from 'react-infinite-scroll-component';

function InfiniteScrollComponent() {
  // ...状态管理逻辑同上

  return (
    <InfiniteScroll
      dataLength={items.length}
      next={loadMore}
      hasMore={true}
      loader={<h4>Loading...</h4>}
    >
      {items.map((item, index) => (
        <div key={index}>{item}</div>
      ))}
    </InfiniteScroll>
  );
}

react实现分页滚动加载

标签: 分页加载
分享给朋友:

相关文章

vue滚动加载实现

vue滚动加载实现

vue滚动加载实现 滚动加载是一种常见的优化手段,通过监听滚动事件动态加载数据,减少初始渲染压力。以下是几种实现方式: 使用IntersectionObserver API Intersectio…

js实现分页

js实现分页

实现分页的基本思路 分页功能通常需要处理数据分割、页码生成和用户交互。核心逻辑包括计算总页数、根据当前页截取数据、渲染页码按钮等。 前端分页实现(静态数据) 假设已有全部数据,仅需前端分页展示:…

vue实现加载

vue实现加载

Vue 实现加载功能的方法 使用 v-if 或 v-show 控制加载状态 在模板中通过 v-if 或 v-show 控制加载动画的显示与隐藏。v-if 会完全移除 DOM 元素,而 v-show 仅…

vue分页实现

vue分页实现

Vue 分页实现方法 基础分页组件实现 创建一个简单的分页组件,包含上一页、下一页和页码按钮。组件接收当前页码、总页数等参数,通过事件通知父组件页码变化。 <template> &l…

vue  实现分页

vue 实现分页

实现分页功能 在Vue中实现分页功能通常需要结合后端API或前端数据处理。以下是两种常见的实现方式: 前端分页实现 适用于数据量较小的情况,所有数据一次性加载到前端后进行分页处理: <…

js实现分页功能代码

js实现分页功能代码

分页功能实现方法 客户端分页(前端处理数据) 适用于数据量较小且已全部加载到前端的情况。 // 示例数据 const data = Array.from({length: 100}, (_, i)…