如何在MUI Slide组件中使用useAutocomplete并解决输入元素找不到报错
解决MUI Slide组件配合useAutocomplete的卸载报错问题
问题原因
你使用了unmountOnExit属性,当isOpen变为false时,Slide组件会在退出动画结束后卸载内部的TextField和List元素。但useAutocomplete的内部逻辑仍会尝试访问input元素的引用,此时input已被卸载、ref变为null,因此触发报错。
解决方案(保留Slide动画+卸载逻辑)
核心思路是仅在组件挂载状态(isOpen为true)时执行useAutocomplete钩子,避免钩子在组件卸载后仍尝试访问无效的input引用。
具体实现代码
import { useAutocomplete, TextField, InputAdornment, SearchIcon, List, Slide } from '@mui/material'; import { useState } from 'react'; const YourComponent = () => { const [isOpen, setIsOpen] = useState(false); const [searchInput, setSearchInput] = useState(''); const options = ['Option 1', 'Option 2', 'Option 3']; // 示例选项 // 仅在isOpen为true时初始化useAutocomplete const autocompleteProps = isOpen ? useAutocomplete({ options, value: searchInput, onChange: (event, newValue) => { setSearchInput(newValue); }, renderOption: (props, option) => ( <li {...props}>{option}</li> ), }) : { // 当isOpen为false时返回空props,避免绑定无效逻辑 getRootProps: () => ({}), getInputLabelProps: () => ({}), getInputProps: () => ({}), getListboxProps: () => ({}) }; const { getRootProps, getInputLabelProps, getInputProps, getListboxProps } = autocompleteProps; const optionsList = autocompleteProps.options?.map((option, index) => ( <li key={index} {...autocompleteProps.getOptionProps({ option })}> {option} </li> )); return ( <> <button onClick={() => setIsOpen(!isOpen)}>Toggle Search</button> <Slide in={isOpen} timeout={{ enter: 300, exit: 200 }} mountOnEnter unmountOnExit > <div {...getRootProps()}> <TextField variant="outlined" label="search" size="small" value={searchInput} autoFocus onChange={(e) => setSearchInput(e.target.value)} InputLabelProps={{ ...getInputLabelProps() }} inputProps={{ ...getInputProps() }} InputProps={{ endAdornment: ( <InputAdornment position="end"> <SearchIcon /> </InputAdornment> ), }} /> {isOpen && <List {...getListboxProps()}>{optionsList}</List>} </div> </Slide> </> ); }; export default YourComponent;
方案说明
- 当
isOpen为false时,给autocompleteProps赋值一组空的方法,避免绑定任何需要访问input元素的逻辑,从根源解决ref为空的报错。 - 当
isOpen切换为true时,正常初始化useAutocomplete,保留所有自动补全功能和Slide的入场/退场动画。 - 额外给List添加
isOpen条件渲染,避免在组件卸载前出现无效的列表内容。
备选方案(不卸载组件,仅视觉隐藏)
如果可以接受组件不卸载(仅视觉隐藏),可以移除unmountOnExit,配合样式控制显示:
<Slide in={isOpen} timeout={{ enter: 300, exit: 200 }} mountOnEnter > <div {...getRootProps()} style={{ display: isOpen ? 'block' : 'none' }} > {/* 内部TextField和List内容 */} </div> </Slide>
这种方式更简单,但组件会一直存在于DOM中,适合对性能影响不大的场景。
内容的提问来源于stack exchange,提问作者Yahli Gitzi
相关产品推荐
相关产品推荐

