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

Material UI Autocomplete组件传入大数据集时渲染延迟问题

Material UI Autocomplete 大数据集渲染延迟问题

在React应用中使用Material UI的Autocomplete组件时,传入约10000条数据的大数据集作为props,下拉菜单渲染出预期数据前会出现约5秒的显著延迟。以下是按照官方文档实现的组件代码:

import * as React from 'react';
import Autocomplete from '@mui/material/Autocomplete';
import TextField from '@mui/material/TextField';
import Checkbox from '@mui/material/Checkbox';
import CheckBoxOutlineBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank';
import CheckBoxIcon from '@mui/icons-material/CheckBox';

const icon = <CheckBoxOutlineBlankIcon fontSize="small" />;
const checkedIcon = <CheckBoxIcon fontSize="small" />;

type AutoSelectDropdownProps = {
    dropdownData?: any[],
    isMultiple?: boolean,
    onChange?: (event: { target: { value: any[]; name?: undefined } }) => void
    defaultvalue?: any[],
    valueField?: string
    displayField?: string,
}

export function AutoCompleteDropDown(props: AutoSelectDropdownProps) {

    let newObj = [...props.dropdownData];

    const loadValues = (event: any, values: any[]) => {
        const target = {
          value: [],
          name: undefined
        };

        if (values && values.length > 0) {
          target.value = values.map((item: any) => item[props.valueField || 'value']);
        }

      props.onChange({target});

    }


  return (
    <Autocomplete
      multiple
      options={newObj}
      getOptionLabel={(option) => option.value}
      limitTags={2}
      onChange={loadValues}
      defaultValue={
        props.dropdownData.filter((item: any) => {
          return props.defaultvalue.includes(item[props.valueField || 'value']);
        })
      }
      renderOption={(props, option, { selected }) => (
        <li {...props}>
          <Checkbox
            icon={icon}
            checkedIcon={checkedIcon}
            checked={selected}
            />
          {option.value}
        </li>
      )}
      size="small"
      sx={{ minWidth: 180, width: '100%', mt: 1, backgroundColor: "white" }}
      renderInput={(params) => (
        <TextField {...params} size='small' />
      )}
    />
  );
}

export default AutoCompleteDropDown;

优化方案

  • 启用虚拟滚动:使用虚拟滚动组件只渲染可视区域内的选项,大幅减少DOM节点数量,避免全量渲染导致的阻塞。
  • 移除无意义数据拷贝:删除let newObj = [...props.dropdownData];,直接使用props.dropdownData作为数据源,减少内存开销。
  • 缓存默认值计算结果:用useMemo包裹默认值的过滤逻辑,避免每次组件渲染都重复执行计算。
  • 优化字段读取逻辑:统一使用displayField和valueField指定的字段,避免硬编码option.value,同时保证字段访问的一致性。
  • 减少组件重渲染:用React.memo包裹Checkbox组件,避免选项状态变化时不必要的重渲染。

修改后的优化代码

import * as React from 'react';
import Autocomplete from '@mui/material/Autocomplete';
import TextField from '@mui/material/TextField';
import Checkbox from '@mui/material/Checkbox';
import CheckBoxOutlineBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank';
import CheckBoxIcon from '@mui/icons-material/CheckBox';
import { FixedSizeList } from 'react-window';

const icon = <CheckBoxOutlineBlankIcon fontSize="small" />;
const checkedIcon = <CheckBoxIcon fontSize="small" />;

// 缓存Checkbox组件减少重渲染
const MemoizedCheckbox = React.memo((props: { checked: boolean }) => (
  <Checkbox
    icon={icon}
    checkedIcon={checkedIcon}
    checked={props.checked}
  />
));

type AutoSelectDropdownProps = {
    dropdownData?: any[],
    isMultiple?: boolean,
    onChange?: (event: { target: { value: any[]; name?: undefined } }) => void
    defaultvalue?: any[],
    valueField?: string
    displayField?: string,
}

export function AutoCompleteDropDown(props: AutoSelectDropdownProps) {
    const valueField = props.valueField || 'value';
    const displayField = props.displayField || 'value';

    // 缓存默认值计算结果
    const defaultValue = React.useMemo(() => {
        if (!props.dropdownData || !props.defaultvalue) return [];
        return props.dropdownData.filter(item => 
            props.defaultvalue.includes(item[valueField])
        );
    }, [props.dropdownData, props.defaultvalue, valueField]);

    const loadValues = (event: any, values: any[]) => {
        const target = {
          value: values?.map(item => item[valueField]) || [],
          name: undefined
        };
        props.onChange?.({target});
    }

    // 虚拟滚动列表组件
    const ListboxComponent = React.useMemo(() => ({ children, ...other }) => (
        <FixedSizeList
            {...other}
            height={300}
            itemSize={40}
            itemCount={children.length}
        >
            {({ index, style }) => (
                <div style={style}>{children[index]}</div>
            )}
        </FixedSizeList>
    ), []);

  return (
    <Autocomplete
      multiple
      options={props.dropdownData || []}
      getOptionLabel={(option) => option[displayField]}
      limitTags={2}
      onChange={loadValues}
      defaultValue={defaultValue}
      renderOption={(props, option, { selected }) => (
        <li {...props}>
          <MemoizedCheckbox checked={selected} />
          {option[displayField]}
        </li>
      )}
      size="small"
      sx={{ minWidth: 180, width: '100%', mt: 1, backgroundColor: "white" }}
      renderInput={(params) => (
        <TextField {...params} size='small' />
      )}
      ListboxComponent={ListboxComponent}
    />
  );
}

export default AutoCompleteDropDown;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 03:52:41