ReactJS 实现双API结果比对的分页下拉选择组件出现接口死循环问题
问题原因分析
你的代码存在3个核心问题直接导致了异常表现:
- React的
setState是异步更新的,你在调用setListaRealm后立刻读取listaRealm拿到的永远是更新前的旧值,所以你返回的选项永远是上一页的旧数据,状态看起来没有更新 - 你在
loadOptions中主动修改组件状态listaRealm,状态更新触发组件重渲染,AsyncPaginate组件重渲染后会重新调用loadOptions接口,直接造成接口循环调用 hasMore判断逻辑完全错误:listaRealm.length >= 1意味着只要存在数据就永远认为还有下一页,永远触发下一页加载,同时没有对两个接口的分页状态做判断,完全不符合你的业务需求
修复方案
const SelectAsyncPaginate = props => { const [realmScelto, setRealmScelto] = useState(null); useEffect(() => { setRealmScelto(props.realmScelto); }, [props.realmScelto]); const loadOptions = async (searchQuery, loadedOptions, { page }) => { // 并行请求两个接口提升加载速度 const [optionToShow, optionToShow2] = await Promise.all([ fetch( `${apiUrl}?page=${page}&size=20&deletedDate.specified=false${searchQuery.length > 3 ? `&appDesapplicazione.contains=${searchQuery}` : ''}` ).then(res => res.json()), fetch( `${apiUrlRealm}?page=${page}&size=20&deletedDate.specified=false` ).then(res => res.json()) ]); // 过滤需要展示的选项 const notPresent = optionToShow2.content.filter(ra => { return !optionToShow.content.some(rua => rua.realm.id === ra.id && rua.user.perCod === props.persona.perCod.perCod); }); // 判断是否还有下一页:两个接口任意一个还有未加载数据就继续翻页,这里假设接口返回Spring Data分页结构,last为true代表是最后一页 const hasMore = !optionToShow.last || !optionToShow2.last; return { // 直接返回当前页处理好的选项即可,AsyncPaginate会自动拼接历史选项 options: notPresent, hasMore: hasMore, additional: { // 搜索关键词变化时重置页码,否则页码累加 page: page + 1, }, }; }; const onChange = option => { if (typeof props.onChange === 'function') { props.onChange(option); } }; return ( <AsyncPaginate value={props.value} loadOptions={loadOptions} // 注意:过滤后的notPresent是realm对象本身,不需要加.realm层级 getOptionValue={option => option.id} getOptionLabel={option => option.realmId} onChange={onChange} isSearchable={true} placeholder="Seleziona Realm" additional={{ page: 0, }} // 搜索时重置页码,避免用之前的页码加载 debounceTimeout={300} /> ); };
注:代码中假设你的分页接口返回的是Spring Data标准分页结构,包含
content(当前页数据数组)、last(是否为最后一页)字段,如果你接口的分页字段不同,替换为对应字段即可,比如hasNextPage、totalPages等。
关键修改点说明
- 移除了自行维护的
listaRealm状态:AsyncPaginate组件会自动管理已加载的所有选项,不需要手动维护,避免状态更新触发的循环调用 - 修正选项取值逻辑:过滤后的选项是realm对象本身,修复了原代码中取
option.realm.id无法获取值的问题 - 修正
hasMore判断逻辑:根据两个接口的实际分页返回结果判断是否还有下一页,不会无限制加载 - 并行请求两个接口:减少请求等待时间,提升组件响应速度
- 新增搜索防抖:避免输入过程中频繁触发接口请求
内容的提问来源于stack exchange,提问作者Jack23
相关产品推荐
相关产品推荐

