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

React MUI Autocomplete问题:选中选项后滚动重置+无法程序化关闭下拉

解决方案:MUI Autocomplete自定义Listbox的滚动位置与下拉框关闭问题

问题1:选择底部选项时滚动位置重置

原因是自定义ListboxComponent随选中状态变化重渲染,导致<ul>元素重新挂载,滚动位置丢失。通过缓存自定义Listbox组件避免不必要的重渲染即可解决:

  1. 提取Listbox为独立组件并使用React.memo包裹:
import React, { memo } from 'react';

const CustomListbox = memo(({ listBoxProps, onClear, onApply }) => {
  return (
    <div>
      <ul {...listBoxProps} />
      <div style={{ padding: '8px', display: 'flex', gap: '8px', justifyContent: 'flex-end' }}>
        <button
          onMouseDown={(e) => e.preventDefault()}
          onClick={onClear}
          style={{ padding: '4px 12px' }}
        >
          Clear All
        </button>
        <button
          onMouseDown={(e) => e.preventDefault()}
          onClick={onApply}
          style={{ padding: '4px 12px' }}
        >
          Apply
        </button>
      </div>
    </div>
  );
});
  1. 在Autocomplete中使用该组件:
<ListboxComponent={(props) => (
  <CustomListbox
    listBoxProps={props}
    onClear={() => {
      setSelected([]);
      setOpen(false);
    }}
    onApply={() => setOpen(false)}
  />
)}

React.memo会对比组件props,只有当listBoxProps、onClear或onApply变化时才重渲染,从而保留<ul>的滚动状态。

问题2:无法程序化关闭下拉框

通过控制Autocomplete的open状态实现手动关闭:

  1. 添加open状态管理:
const [open, setOpen] = useState(false);
  1. 给Autocomplete绑定状态与回调:
<Autocomplete
  open={open}
  onOpen={() => setOpen(true)}
  onClose={() => setOpen(false)}
  // 其他属性...
/>
  1. 在按钮点击时更新open状态:
  • Clear All按钮:清空选中值后设置open=false
  • Apply按钮:直接设置open=false

完整代码示例

整合后的核心代码片段:

import React, { useState, memo } from 'react';
import Autocomplete from '@mui/material/Autocomplete';
import Checkbox from '@mui/material/Checkbox';
import ListItemText from '@mui/material/ListItemText';

const CustomListbox = memo(({ listBoxProps, onClear, onApply }) => {
  return (
    <div>
      <ul {...listBoxProps} />
      <div style={{ padding: '8px', display: 'flex', gap: '8px', justifyContent: 'flex-end' }}>
        <button
          onMouseDown={(e) => e.preventDefault()}
          onClick={onClear}
          style={{ padding: '4px 12px' }}
        >
          Clear All
        </button>
        <button
          onMouseDown={(e) => e.preventDefault()}
          onClick={onApply}
          style={{ padding: '4px 12px' }}
        >
          Apply
        </button>
      </div>
    </div>
  );
});

export default function MultiSelectAutocomplete() {
  const [selected, setSelected] = useState([]);
  const [open, setOpen] = useState(false);
  const options = Array.from({ length: 50 }, (_, i) => `Option ${i + 1}`);

  return (
    <Autocomplete
      multiple
      open={open}
      onOpen={() => setOpen(true)}
      onClose={() => setOpen(false)}
      options={options}
      value={selected}
      onChange={(event, selectedOptions) => setSelected(selectedOptions)}
      renderOption={(optionProps, option, optionState) => (
        <li {...optionProps}>
          <Checkbox checked={optionState.selected} />
          <ListItemText primary={option} />
        </li>
      )}
      ListboxComponent={(props) => (
        <CustomListbox
          listBoxProps={props}
          onClear={() => {
            setSelected([]);
            setOpen(false);
          }}
          onApply={() => setOpen(false)}
        />
      )}
      renderInput={(params) => (
        <div {...params.container}>
          <input {...params.inputProps} />
        </div>
      )}
    />
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 01:16:11