validateDOMNesting(...): <button> 警告

3

我正在使用React制作网站。

当我的网站有很多文本时,我会显示一个按钮,例如“显示更多或更少”。

在我的项目中,它运行良好,但总是显示一个关于validateDOMNesting(...): <button>的警告。

我示例代码如下。

const [show, setShow] = useState(false);

function handleShow() {
  show ? setShow(false) : setShow(true);
}

<CardActionArea>
  <Button onClick={handleShow}> 
    { show ? text : text.substr(0, 100) + "..." }
  </Button>
</CardActionArea>

我认为CardActionArea是一个按钮组件,它现在嵌套了一个button

但如果我在button中声明href属性,它不会产生警告。

有没有一种好的方式,在不使用href属性的情况下不会产生警告?


你能否用最简单的例子在codesandbox.io中重新创建警告? - Dennis Vash
1个回答

8

问题:您的代码将一个按钮放在另一个按钮中,这是不允许的。

从 Material-UI CardActionArea 文档 中可以看到:

继承

ButtonBase 组件的属性也是可用的。您可以利用这种行为来定位嵌套组件。

如果您转到 ButtonBase 文档,您会看到它默认是一个 'button' 组件。

enter image description here

选项 1:将按钮逻辑移到 CardActionArea 中,并将 Buttoncomponent 属性设置为任何非按钮元素,如 span 元素。这使得整个卡片操作区域都具有 onClick 处理程序和响应式。

<CardActionArea onClick={handleShow}>
  <Button component="span"> 
    { show ? text : text.substr(0, 100) + "..." }
  </Button>
</CardActionArea>
选项 2:保持原样并将 CardActionArea 组件的属性设置为除 'button' 之外的任何其他 值。这将仅保留带有 onClick 处理程序的按钮,卡操作区域将注册单击,即涟漪效果,但否则将不起作用。
<CardActionArea component="span">
  <Button onClick={handleShow}> 
    { show ? text : text.substr(0, 100) + "..." }
  </Button>
</CardActionArea>

卡片操作区内的编辑按钮

在两个选项中,我认为选项1更好,因为它使整个动作区域具有响应性,但这完全基于所呈现的事实和你的需求/设计可能不同或更复杂。


嗨,它真的很好用。非常感谢你的帮助。我可以再问一个问题吗? 在我的代码中,CardActionArea 中有很多东西,所以我无法在 CardActionArea 中放置 onClick 选项。 我想问一下为什么你把 onClick 放在 CardActionArea 而不是 Button 中? 在我的情况下,尽管我把所有东西都放在 Button 的 onClick 和 component="span" 中,但它仍然很好用。 - mimic
1
@mimic 当然可以。仅仅只有一个按钮,整个操作区域看起来都是“可交互”的,即视觉上的“触觉”反馈涟漪效果,这让我感到有些奇怪,但实际上只有按钮才能起作用。但这也是我在最后添加了关于选项和不知道你具体情况和使用方式的注释的原因。 - Drew Reese
非常感谢您的帮助。正如我之前提到的,除了按钮之外,我在CardActionArea中做了很多事情。再次感谢您的帮助!!! - mimic
从可访问性的角度考虑,你应该将“动作”与可以启动它的元素保持一致。例如,使用屏幕阅读器或以其他方式导航您的页面(视觉障碍者)可能不明白他们可以与一个span交互,因为在这种情况下这没有任何意义。如果您这样做,请确保使用适当的ARIA属性来解决任何可访问性需求。 - Drew Reese
有没有办法在悬停按钮时禁用 CardActionArea 上的悬停涟漪效果? - Simon Tran
@SimonTran 按钮有一个 disableRipple 属性,但我认为你在询问的是悬停高亮效果。你可以覆盖一些 CSS 来禁用按钮的悬停样式,或者似乎在 Button 上使用 fullWidth 属性使它只覆盖而不显示“双重悬停”效果(嗯,实际上是会显示的,但它被应用于整个宽度,与卡片操作区域相同)。如果你对稍微深一点的悬停样式感到困扰,那么就选择我建议的第一种选项,并覆盖一些 CSS 规则。 - Drew Reese

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接