React MUI Autocomplete问题:选中选项后滚动重置+无法程序化关闭下拉
解决方案:MUI Autocomplete自定义Listbox的滚动位置与下拉框关闭问题
问题1:选择底部选项时滚动位置重置
原因是自定义ListboxComponent随选中状态变化重渲染,导致<ul>元素重新挂载,滚动位置丢失。通过缓存自定义Listbox组件避免不必要的重渲染即可解决:
- 提取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> ); });
- 在Autocomplete中使用该组件:
<ListboxComponent={(props) => ( <CustomListbox listBoxProps={props} onClear={() => { setSelected([]); setOpen(false); }} onApply={() => setOpen(false)} /> )}
React.memo会对比组件props,只有当listBoxProps、onClear或onApply变化时才重渲染,从而保留<ul>的滚动状态。
问题2:无法程序化关闭下拉框
通过控制Autocomplete的open状态实现手动关闭:
- 添加
open状态管理:
const [open, setOpen] = useState(false);
- 给Autocomplete绑定状态与回调:
<Autocomplete open={open} onOpen={() => setOpen(true)} onClose={() => setOpen(false)} // 其他属性... />
- 在按钮点击时更新
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
相关产品推荐
相关产品推荐

