react-select-async-paginate滚动不加载 万级下拉无卡顿方案
问题根因
你的代码有3个核心错误,导致分页加载逻辑不生效:
- 违反React Hook使用规则:在普通异步函数
LoadOptions中调用useState,Hook仅能在React组件或自定义Hook的顶层执行,在普通异步函数中调用不仅会抛出运行时错误,还会导致你定义的prevLast状态每次函数执行时都被重置为0,完全无法持久化分页偏移量。 - 未使用组件官方的分页状态传递机制:
react-select-async-paginate的分页游标不需要开发者自行在函数内存储,而是通过loadOptions的第三个入参(上一次请求返回的附加状态)、以及返回值中的additional字段在组件内部维护,你没有实现这套逻辑,组件无法获取下一页的请求参数,自然不会在滚动时触发后续加载。 - 分页逻辑硬编码错误:之前的偏移量计算逻辑错误(误将单页数据长度作为下一次偏移量,而非累计已加载总数),且
hasMore固定为true,数据全部加载完成后还会持续触发无效请求。
正确实现代码
首先调整LoadOptions逻辑,移除所有Hook调用,通过组件约定的参数传递分页状态,建议固定单页加载条数为50-100,平衡请求次数和渲染性能:
const sleep = (ms) => new Promise((resolve) => { setTimeout(resolve, ms); }); const baseurl = "http://localhost:5000/api"; // 单页加载条数,建议设置为50-100 const PAGE_SIZE = 80; const LoadOptions = async (search, prevOptions, { offset }) => { await sleep(300); // 向后端传递偏移量、单页大小、搜索关键词 const response = await fetch( `${baseurl}/pdt?offset=${offset}&limit=${PAGE_SIZE}&keyword=${encodeURIComponent(search)}` ); const pList = await response.json(); const pdtList = pList.map(item => ({ label: item.pdtno, value: item.pdtno })); // 返回数据长度小于单页大小,说明已经是最后一页 const hasMore = pdtList.length === PAGE_SIZE; return { options: pdtList, hasMore, // 传递下一次请求的偏移量,存在additional字段中由组件维护 additional: { offset: offset + pdtList.length } }; }; export default LoadOptions;
再调整select组件配置,传入初始分页参数、开启防抖优化体验:
import React, { useState } from "react"; import { AsyncPaginate } from "react-select-async-paginate"; import LoadOptions from "./LoadOptions"; const TooManySelect = () => { const [value, onChange] = useState(null); return ( <div className="Select-options"> <label>Pdt code</label> <AsyncPaginate defaultOptions value={value} loadOptions={LoadOptions} onChange={onChange} // 初始分页参数,首次加载从第0条开始 additional={{ offset: 0 }} // 搜索防抖,避免输入过程中频繁发起请求 debounceTimeout={300} // 距离菜单底部100px时提前触发下一页加载,滚动更流畅 menuScrollThreshold={100} /> </div> ); }; export default TooManySelect;
大数量场景卡顿优化
如果需要加载上万条选项,仅做分页还不够,累计渲染上千个DOM节点依然会卡顿,可以搭配以下优化:
- 开启虚拟滚动:自定义
MenuList组件,用虚拟滚动方案只渲染可视区域内的选项,哪怕全量加载2万条数据,页面也不会卡顿。 - 优化后端分页查询:避免使用大偏移量的
OFFSET语法,数据量越大OFFSET查询性能越差,可改为基于主键游标的分页(以上一次查询的最后一条记录ID作为下次查询的起始条件),查询速度能提升数倍。 - 强化搜索能力:支持拼音、模糊匹配等搜索逻辑,引导用户通过输入关键词快速定位选项,减少滚动加载的数据量。
内容的提问来源于stack exchange,提问作者Maya
相关产品推荐
相关产品推荐

