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

如何为MUI AutoComplete组件添加无限滚动功能?

实现MUI5 AutoComplete滚动加载分页数据的方案

下面是一套可直接复用的实现方案,解决滚动下拉列表底部加载下一页数据的需求:

核心逻辑

  • 通过useRef获取AutoComplete的下拉面板DOM节点,监听其滚动事件
  • 滚动到接近底部时(预留小阈值),触发下一页数据请求
  • 维护数据列表、当前页码、加载状态、是否还有更多数据这几个核心状态,避免重复请求和无效加载
  • 新数据请求成功后合并到已有列表,加载过程中在列表底部显示状态提示

完整代码实现

import React, { useState, useRef, useEffect, useCallback } from 'react';
import Autocomplete from '@mui/material/Autocomplete';
import TextField from '@mui/material/TextField';
import CircularProgress from '@mui/material/CircularProgress';
import ListItem from '@mui/material/ListItem';
import Typography from '@mui/material/Typography';

// 替换成你实际的分页接口
const fetchPaginatedData = async (page = 1, searchQuery = '') => {
  // 模拟接口延迟和返回数据,实际开发中替换为真实API调用
  await new Promise(resolve => setTimeout(resolve, 800));
  const mockData = Array.from({ length: 10 }, (_, i) => ({
    id: (page - 1) * 10 + i + 1,
    label: `${searchQuery || 'Item'} ${(page - 1) * 10 + i + 1}`
  }));
  // 模拟第3页之后没有更多数据,实际根据接口返回判断
  return page > 3 ? [] : mockData;
};

const PaginatedAutoComplete = () => {
  const [options, setOptions] = useState([]);
  const [page, setPage] = useState(1);
  const [isLoading, setIsLoading] = useState(false);
  const [hasMore, setHasMore] = useState(true);
  const [searchQuery, setSearchQuery] = useState('');
  const listboxRef = useRef(null);

  // 加载下一页数据
  const loadNextPage = useCallback(async () => {
    if (isLoading || !hasMore) return;
    setIsLoading(true);
    try {
      const newData = await fetchPaginatedData(page, searchQuery);
      if (newData.length === 0) {
        setHasMore(false);
      } else {
        setOptions(prev => [...prev, ...newData]);
        setPage(prev => prev + 1);
      }
    } catch (error) {
      console.error('加载数据失败:', error);
      // 可根据需求添加前端错误提示
    } finally {
      setIsLoading(false);
    }
  }, [page, isLoading, hasMore, searchQuery]);

  // 监听下拉面板滚动事件
  useEffect(() => {
    const listbox = listboxRef.current;
    if (!listbox) return;

    const handleScroll = () => {
      // 滚动到距离底部20px时触发加载,可根据需求调整阈值
      if (listbox.scrollTop + listbox.clientHeight >= listbox.scrollHeight - 20) {
        loadNextPage();
      }
    };

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

  // 搜索词变化时重置数据和页码
  useEffect(() => {
    setOptions([]);
    setPage(1);
    setHasMore(true);
    // 300ms防抖,避免输入时频繁触发请求
    const timer = setTimeout(() => {
      loadNextPage();
    }, 300);
    return () => clearTimeout(timer);
  }, [searchQuery]);

  // 自定义下拉项渲染,添加加载提示
  const renderOption = (props, option) => {
    // 加载提示项(用特殊标识区分普通选项)
    if (option.isLoading) {
      return (
        <ListItem {...props} disabled>
          <CircularProgress size={20} sx={{ mr: 1 }} />
          <Typography>加载中...</Typography>
        </ListItem>
      );
    }
    return (
      <ListItem {...props}>
        <Typography>{option.label}</Typography>
      </ListItem>
    );
  };

  // 拼接加载提示项到选项列表
  const displayOptions = hasMore && isLoading 
    ? [...options, { isLoading: true }] 
    : options;

  return (
    <Autocomplete
      options={displayOptions}
      getOptionLabel={(option) => option.label || ''}
      renderOption={renderOption}
      onInputChange={(event, newInputValue) => {
        setSearchQuery(newInputValue);
      }}
      renderInput={(params) => (
        <TextField
          {...params}
          label="分页搜索"
          variant="outlined"
          fullWidth
        />
      )}
      // 给下拉面板设置ref和滚动容器样式
      ListboxProps={{
        ref: listboxRef,
        sx: {
          maxHeight: 300,
          overflowY: 'auto',
        },
      }}
    />
  );
};

export default PaginatedAutoComplete;

关键细节说明

  • 滚动阈值:设置20px的提前加载阈值,避免用户滚动到底部才开始加载,提升流畅度
  • 防抖处理:搜索词变化时加300ms防抖,减少不必要的API请求
  • 状态控制:用isLoading防止重复请求,hasMore控制是否继续加载,避免无意义调用API
  • 搜索重置:用户输入新关键词时,清空现有数据、重置页码,重新从第一页开始加载
  • 加载提示:在列表底部添加加载动画,让用户明确知道正在加载更多数据

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 11:01:33