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

MUI单个Button组件绑定双Tooltip实现报错及解决方案咨询

解决MUI Button上添加两个Tooltip的嵌套报错问题

我来帮你搞定这个问题!你遇到的报错是因为MUI的Tooltip组件内置了校验逻辑——它不允许直接嵌套使用Tooltip(或者子元素带有title属性),这是官方为了避免交互冲突和语义混淆做的限制,哪怕用forwardRef封装也绕不开这个校验,因为外层Tooltip依然能检测到内部组件里的Tooltip相关属性。

下面给你两个可行的解决方案,都不会破坏你的布局:

方案一:手动控制两个Tooltip的显示状态(无嵌套)

我们可以通过监听Button的鼠标事件,手动控制两个Tooltip的open状态,完全避免嵌套结构:

import * as React from 'react';
import { Tooltip, Button, Box } from '@mui/material';

export default function DoubleTooltipButton() {
  const [topTooltipOpen, setTopTooltipOpen] = React.useState(false);
  const [bottomTooltipOpen, setBottomTooltipOpen] = React.useState(false);

  const handleMouseEnter = () => {
    setTopTooltipOpen(true);
    setBottomTooltipOpen(true);
  };

  const handleMouseLeave = () => {
    setTopTooltipOpen(false);
    setBottomTooltipOpen(false);
  };

  return (
    <Box sx={{ margin: 10, position: 'relative' }}>
      {/* 顶部Tooltip:关闭默认hover监听,手动控制显示 */}
      <Tooltip
        title="Tooltip on top"
        placement="top"
        open={topTooltipOpen}
        disableHoverListener
      />
      {/* 底部Tooltip:同样手动控制 */}
      <Tooltip
        title="Tooltip on bottom"
        placement="bottom"
        open={bottomTooltipOpen}
        disableHoverListener
      />
      {/* 绑定事件的目标Button */}
      <Button
        onMouseEnter={handleMouseEnter}
        onMouseLeave={handleMouseLeave}
      >
        Hello
      </Button>
    </Box>
  );
}

方案说明:

  • 把两个Tooltip和Button放在同一个父容器中,完全去掉嵌套
  • 用open属性手动控制Tooltip的显示/隐藏,同时通过disableHoverListener关闭Tooltip自带的hover逻辑,避免和我们手动绑定的事件冲突
  • 父容器设置position: 'relative'是为了确保Tooltip的定位基准正确,如果你的业务布局已经有相对定位的父容器,可以省略这个样式

方案二:用Popper组件自定义第二个Tooltip

如果需要更灵活的样式控制,也可以直接用MUI的Popper组件(Tooltip本质就是基于Popper封装的)来实现第二个提示,这样既不会触发嵌套报错,还能自定义提示内容:

import * as React from 'react';
import { Tooltip, Button, Box, Popper, Typography, Paper } from '@mui/material';

export default function DoubleTooltipButton() {
  const [isBottomTooltipOpen, setIsBottomTooltipOpen] = React.useState(false);
  const buttonRef = React.useRef(null);

  const handleMouseEnter = () => setIsBottomTooltipOpen(true);
  const handleMouseLeave = () => setIsBottomTooltipOpen(false);

  return (
    <Box sx={{ margin: 10 }}>
      {/* 保留一个原生Tooltip用于顶部提示 */}
      <Tooltip title="Tooltip on top" placement="top">
        <Button 
          ref={buttonRef} 
          onMouseEnter={handleMouseEnter} 
          onMouseLeave={handleMouseLeave}
        >
          Hello
        </Button>
      </Tooltip>
      {/* 用Popper自定义底部提示 */}
      <Popper 
        open={isBottomTooltipOpen} 
        anchorEl={buttonRef.current} 
        placement="bottom"
      >
        <Paper sx={{ padding: '8px 12px', borderRadius: 0.5 }}>
          <Typography variant="body2" color="inherit">
            Tooltip on bottom
          </Typography>
        </Paper>
      </Popper>
    </Box>
  );
}

方案优势:

  • 可以完全自定义提示框的样式、内容,比如修改背景色、字体大小等
  • 同样不需要嵌套Tooltip,完美绕过MUI的校验逻辑
  • 布局上不会添加任何干扰元素,完全符合你的业务需求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 14:27:27