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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 13:23:22