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

如何在React+Redux中实现滚动加载分页优化700+记录性能

实现React+Redux下的滚动懒加载优化性能

我之前也碰到过一次性加载几百条数据导致页面卡顿、加载耗时久的问题,用滚动懒加载完全解决了这个痛点。结合你用的React+Redux技术栈,给你梳理一套完整的落地方案:

第一步:Redux状态层设计

首先要在Redux的状态里维护分页相关的核心参数,比如当前页码、每页条数、加载状态、是否还有更多数据,以及已经加载的列表数据。

示例Reducer

// reducers/listReducer.js
const initialState = {
  data: [],
  currentPage: 1,
  pageSize: 20,
  isLoading: false,
  hasMore: true, // 标记是否还有剩余数据可加载
};

const listReducer = (state = initialState, action) => {
  switch (action.type) {
    case 'LIST_LOAD_START':
      return { ...state, isLoading: true };
    case 'LIST_LOAD_SUCCESS':
      // 合并新数据到已有列表
      const newData = [...state.data, ...action.payload];
      // 判断是否还有更多:如果返回的新数据量小于每页条数,说明没有剩余了
      const hasMore = action.payload.length === state.pageSize;
      return {
        ...state,
        data: newData,
        currentPage: state.currentPage + 1,
        isLoading: false,
        hasMore,
      };
    case 'LIST_LOAD_FAILURE':
      return { ...state, isLoading: false };
    default:
      return state;
  }
};

export default listReducer;

对应的Action Creators

// actions/listActions.js
export const loadListStart = () => ({ type: 'LIST_LOAD_START' });
export const loadListSuccess = (data) => ({ type: 'LIST_LOAD_SUCCESS', payload: data });
export const loadListFailure = () => ({ type: 'LIST_LOAD_FAILURE' });

// 异步请求的Thunk(如果用redux-thunk中间件)
export const fetchList = (page, pageSize) => async (dispatch) => {
  dispatch(loadListStart());
  try {
    // 替换成你的实际API请求,传入分页参数
    const response = await fetch(`/api/your-list?page=${page}&pageSize=${pageSize}`);
    const data = await response.json();
    dispatch(loadListSuccess(data));
  } catch (error) {
    dispatch(loadListFailure());
    console.error('列表加载失败:', error);
  }
};

第二步:React组件实现滚动监听与加载逻辑

组件需要完成三个核心动作:首次加载第一页数据、监听滚动事件判断是否触底、触底时触发下一页加载(还要避免重复请求)。

示例组件

// components/ScrollList.js
import React, { useEffect, useRef } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { fetchList } from '../actions/listActions';

const ScrollList = () => {
  const dispatch = useDispatch();
  const { data, currentPage, pageSize, isLoading, hasMore } = useSelector(state => state.list);
  const listContainerRef = useRef(null);

  // 首次加载第一页数据
  useEffect(() => {
    dispatch(fetchList(1, pageSize));
  }, [dispatch, pageSize]);

  // 监听滚动事件
  useEffect(() => {
    const handleScroll = () => {
      // 正在加载或没有更多数据时,直接返回
      if (isLoading || !hasMore) return;

      const container = listContainerRef.current;
      // 提前100px触发加载(提升用户体验,避免等待)
      const isNearBottom = container.scrollTop + container.clientHeight >= container.scrollHeight - 100;
      if (isNearBottom) {
        dispatch(fetchList(currentPage, pageSize));
      }
    };

    const container = listContainerRef.current;
    container.addEventListener('scroll', handleScroll);
    // 组件卸载时移除监听
    return () => container.removeEventListener('scroll', handleScroll);
  }, [dispatch, currentPage, pageSize, isLoading, hasMore]);

  return (
    <div 
      ref={listContainerRef}
      style={{ height: '80vh', overflowY: 'auto', border: '1px solid #eee' }}
    >
      {data.map(item => (
        <div key={item.id} style={{ padding: '16px', borderBottom: '1px solid #f0f0f0' }}>
          {/* 替换成你的列表项内容 */}
          <h4>{item.title}</h4>
          <p>{item.description}</p>
        </div>
      ))}
      {/* 加载状态提示 */}
      {isLoading && <div style={{ textAlign: 'center', padding: '16px', color: '#666' }}>加载中...</div>}
      {/* 无更多数据提示 */}
      {!hasMore && !isLoading && <div style={{ textAlign: 'center', padding: '16px', color: '#999' }}>已加载全部数据</div>}
    </div>
  );
};

export default ScrollList;

第三步:关键注意事项

  • 防止重复请求:必须在滚动监听里判断isLoading状态,避免用户快速滚动时触发多次重复请求
  • 提前加载优化:不要等到完全滚动到底部才触发请求,提前100px左右触发,让用户几乎感知不到加载等待
  • 边界判断:当API返回的数据量小于每页条数时,把hasMore设为false,停止后续加载逻辑
  • 进阶性能优化:如果后续列表总条数还是很大,可以配合React.memo优化列表项渲染,或者用react-window实现虚拟列表,进一步减少DOM节点数量
  • 错误处理:记得处理API请求失败的场景,比如给用户显示错误提示,或者提供重试按钮

这套方案落地后,就能实现首次加载20条、滚动触底自动加载下20条的效果,彻底解决一次性加载700+条的性能问题,加载耗时会降到单次API请求的时间,用户体验会提升很多。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 03:14:04