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

如何在MUI Autocomplete组件末尾添加加载更多按钮

给MUI Autocomplete添加「加载更多」按钮实现方案

核心实现思路

借助MUI Autocomplete的renderListbox属性自定义列表内容,在选项列表末尾追加加载按钮,结合状态管理实现分页加载逻辑,避免一次性加载大量数据导致的性能问题。

完整代码示例

import { useState, useEffect } from 'react';
import { Autocomplete, TextField, Chip, Button, CircularProgress } from '@mui/material';

// 定义数据类型
interface Film {
  id: number;
  title: string;
}

// 模拟分页接口请求
const fetchFilms = async (page: number): Promise<Film[]> => {
  // 替换为真实接口请求逻辑
  await new Promise(resolve => setTimeout(resolve, 1000));
  return Array.from({ length: 20 }, (_, i) => ({
    id: (page - 1) * 20 + i + 1,
    title: `电影 ${(page - 1) * 20 + i + 1}`
  }));
};

const LoadMoreAutocomplete = () => {
  const [items, setItems] = useState<Film[]>([]);
  const [isLoading, setIsLoading] = useState(false);
  const [page, setPage] = useState(1);
  const [isOpen, setIsOpen] = useState(false);

  // 首次打开组件时加载第一页数据
  useEffect(() => {
    if (isOpen && items.length === 0) {
      loadMore();
    }
  }, [isOpen, items.length]);

  // 加载更多数据的核心逻辑
  const loadMore = async () => {
    if (isLoading) return; // 防止重复触发请求
    setIsLoading(true);
    const newItems = await fetchFilms(page);
    setItems(prev => [...prev, ...newItems]);
    setPage(prev => prev + 1);
    setIsLoading(false);
  };

  return (
    <Autocomplete
      multiple
      id="tags-filled"
      options={items.map(item => item.title)}
      defaultValue={items.length > 13 ? [items[13].title] : []}
      freeSolo
      open={isOpen}
      onOpen={() => setIsOpen(true)}
      onClose={() => setIsOpen(false)}
      renderTags={(value: readonly string[], getTagProps) =>
        value.map((option: string, index: number) => (
          <Chip variant="outlined" label={option} {...getTagProps({ index })} />
        ))
      }
      renderInput={(params) => (
        <TextField
          {...params}
          variant="filled"
          label="freeSolo"
          placeholder="Favorites"
        />
      )}
      // 自定义列表框内容,追加加载更多按钮
      renderListbox={(children) => (
        <>
          {children}
          <div style={{ padding: '8px', textAlign: 'center' }}>
            {isLoading ? (
              <CircularProgress size={24} />
            ) : (
              <Button onClick={loadMore} variant="text">
                加载更多
              </Button>
            )}
          </div>
        </>
      )}
    />
  );
};

export default LoadMoreAutocomplete;

关键部分说明

  • 状态控制:用items存储已加载的选项数据,isLoading标记请求状态避免重复调用,page记录当前分页页码。
  • 初始加载触发:通过onOpen事件和useEffect监听,在组件首次打开时自动加载第一页数据。
  • 列表自定义:renderListbox接收默认渲染的选项列表children,在其后添加加载按钮区域,根据isLoading状态切换显示加载动画或可点击按钮。
  • 加载逻辑:loadMore函数负责发起分页请求,更新数据列表和页码,同时维护加载状态。

扩展优化点

  • 可添加滚动监听,当列表滚动到底部时自动触发loadMore,替代点击按钮的交互。
  • 当接口返回空数据时,可将加载按钮替换为「已加载全部」的提示文本,避免无效请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 08:23:55