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

MUI自定义Tooltip包裹TextField时状态变更触发失焦问题求助

问题根因

你遇到的问题核心原因是自定义Tooltip组件CustomWidthTooltip被定义在了App组件的内部:

  • 每次在TextField输入内容触发formData状态更新时,整个App组件都会重新渲染
  • 组件重渲染时会重新生成一个全新的CustomWidthTooltip构造函数,React会判定这是不同类型的组件,因此会卸载旧的Tooltip及其内部的所有子组件,再挂载新的Tooltip和子组件
  • 原有被卸载的TextField自然会失去焦点,新挂载的TextField默认也不会自动获得焦点,就出现了每次只能输入一个字符的问题
  • 未嵌套Tooltip的TextField、以及用官方自带Tooltip的场景不会触发这个问题,是因为这些组件都没有在每次重渲染时被重建

修复方案

把CustomWidthTooltip的定义移到App组件外部即可,修复后的代码如下:

import { useState } from "react";
import { TextField, Box } from "@mui/material";
import { styled } from "@mui/material/styles";
import Tooltip, { tooltipClasses } from "@mui/material/Tooltip";

// 把自定义Tooltip移到组件外部定义,全局仅初始化一次
const CustomWidthTooltip = styled(({ className, ...props }) => (
  <Tooltip {...props} classes={{ popper: className }} />
))({
  [`& .${tooltipClasses.tooltip}`]: {
    maxWidth: 400
  }
});

export default function App() {
  const [formData, setFormData] = useState({
    title: "",
    name: ""
  });

  const handleFormChange = (e) => {
    const { name, value } = e.target;
    setFormData((formData) => {
      return {
        ...formData,
        [name]: value
      };
    });
  };

  return (
    <Box component="form" display="flex">
      <TextField
        onChange={handleFormChange}
        autoComplete="title"
        name="title"
        id="title"
        label="Title"
        required
      />
      <CustomWidthTooltip title="Foo">
        <TextField
          onChange={handleFormChange}
          autoComplete="name"
          name="name"
          id="name"
          label="Name"
          required
        />
      </CustomWidthTooltip>
    </Box>
  );
}

额外注意事项

  • 所有基于MUI styled生成的自定义组件,都不要放在业务组件内部定义,避免每次重渲染重复生成组件实例导致的卸载重挂载问题
  • 如果确实有需要基于组件内部props动态生成样式的场景,可以用styled组件的props传参能力,不要直接把styled定义写在组件内部

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 23:54:02