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

React切换Autocomplete与TextField组件后输入内容丢失问题求助

问题描述

我有Autocomplete和TextField两个组件,要求同一时间仅展示其中一个:当输入内容包含斜杠(/)时显示TextField组件,否则显示Autocomplete组件。

我编写了如下代码:

export default function ComboBox() {
  const [show, setShow] = React.useState(false);
  const [value, setvalue] = React.useState('');
  const onchange = (e) => {
    const inputValue = event?.target?.value || newValue || '';

    setvalue(inputValue);
    setShow((prevState) => {
      const newState = inputValue?.includes('/');
      if (prevState !== newState) {
        if (newState) {
          setTimeout(() => {
            document.getElementById('outlined-basic')?.focus();
          }, 10);
        } else {
          setTimeout(() => {
            document.getElementById('combo-box-demo')?.focus();
          }, 10);
        }
      }
      return newState;
    });
  };

  return (
    <div>
      {show ? (
        <TextField
          id="outlined-basic"
          label="Outlined"
          variant="outlined"
          value={value}
          onChange={onchange}
        />
      ) : (
        <Autocomplete
          disablePortal
          id="combo-box-demo"
          options={top100Films}
          inputValue={value}
          // defaultValue={'abc'}
          onInputChange={onchange}
          sx={{ width: 300 }}
          renderInput={(params) => <TextField {...params} label="Movie" />}
        />
      )}
    </div>
  );
}

当前问题:初始渲染正常,输入the/会正确切换到TextField组件;但移除斜杠后,Autocomplete组件显示但输入内容为空,不符合预期。预期移除斜杠后应恢复输入the时的筛选列表状态。

复现步骤

  • 运行项目
  • 在Autocomplete中输入the,显示筛选列表
  • 输入/,切换到TextField且内容为the/,此步骤正常
  • 移除/
  • Autocomplete字段为空,出现问题

解决方案

问题原因

  1. 事件参数错误:onchange函数定义了参数e,但内部使用全局event变量,导致Autocomplete触发onInputChange时无法正确获取输入值,进而让value状态更新错误。
  2. 输入值逻辑不兼容:TextField的onChange仅传递事件对象,而Autocomplete的onInputChange传递事件对象和newValue,原代码未区分这两种场景的输入值获取方式。
  3. DOM聚焦方式不可靠:依赖getElementById和setTimeout聚焦输入框,容易受DOM渲染时机影响,出现元素未挂载或id不匹配的情况。

修复后的代码

import React from 'react';
import TextField from '@mui/material/TextField';
import Autocomplete from '@mui/material/Autocomplete';

// 示例电影数据,根据实际情况替换
const top100Films = [
  { label: 'The Shawshank Redemption', year: 1994 },
  { label: 'The Godfather', year: 1972 },
  { label: 'The Dark Knight', year: 2008 },
];

export default function ComboBox() {
  const [showTextField, setShowTextField] = React.useState(false);
  const [inputValue, setInputValue] = React.useState('');
  const autoCompleteInputRef = React.useRef(null);
  const textFieldInputRef = React.useRef(null);

  // 监听组件切换状态,自动聚焦对应输入框
  React.useEffect(() => {
    if (showTextField) {
      textFieldInputRef.current?.focus();
    } else {
      autoCompleteInputRef.current?.focus();
    }
  }, [showTextField]);

  const handleInputChange = (e, newValue) => {
    // 兼容两种组件的输入值获取逻辑
    const value = newValue !== undefined ? newValue : e.target.value;
    setInputValue(value);
    
    // 判断是否切换到TextField
    const shouldShowTextField = value.includes('/');
    setShowTextField(shouldShowTextField);
  };

  return (
    <div>
      {showTextField ? (
        <TextField
          ref={textFieldInputRef}
          id="outlined-basic"
          label="Outlined"
          variant="outlined"
          value={inputValue}
          onChange={handleInputChange}
        />
      ) : (
        <Autocomplete
          disablePortal
          id="combo-box-demo"
          options={top100Films}
          inputValue={inputValue}
          onInputChange={handleInputChange}
          sx={{ width: 300 }}
          renderInput={(params) => (
            <TextField 
              {...params} 
              label="Movie" 
              inputProps={{ ...params.inputProps, ref: autoCompleteInputRef }} 
            />
          )}
        />
      )}
    </div>
  );
}

修复说明

  1. 修正事件参数:将全局event替换为函数参数e,确保正确获取事件对象中的输入值。
  2. 兼容输入值获取:根据newValue是否存在,分别处理TextField和Autocomplete的输入值,保证inputValue状态更新准确。
  3. 使用Ref实现可靠聚焦:通过useRef获取输入框元素,结合useEffect监听组件切换状态,在组件渲染完成后自动聚焦,避免依赖setTimeout和DOM查询。
  4. 优化变量命名:将show改为showTextField,setvalue改为setInputValue,提升代码可读性和语义化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 23:58:11