<div>不能显示为<p>的后代


112

我看到了 它抱怨的不是什么神秘的事情:

Warning: validateDOMnesting(...): <div> cannot appear as a descendant of <p>. See ... SomeComponent > p > ... > SomeOtherComponent > ReactTooltip > div.

我的作者SomeComponentSomeOtherComponent。但是后者正在使用外部依赖项(ReactTooltipfrom react-tooltip)。这可能不是一个外部依赖关系,但这不是必须的,但是它让我在这里尝试使用“某些代码超出了我的控制”这一论点。

考虑到嵌套组件工作正常(貌似),我应该为这个警告感到多担心?而且无论如何我将如何进行更改(前提是我不想重新实现外部依赖项)?是否有我尚未意识到的更好的设计?

为了完整起见,这里是的实现SomeOtherComponent。它只是呈现this.props.value,并且在悬停时:提示“某些提示信息”的提示:

class SomeOtherComponent extends React.Component {
  constructor(props) {
    super(props)
  }

  render() {
    const {value, ...rest} = this.props;
    return <span className="some-other-component">
      <a href="#" data-tip="Some tooltip message" {...rest}>{value}</a>
      <ReactTooltip />
    </span>
  }
}

谢谢。


Answers:


109

如果在使用Material UI <Typography> https://material-ui.com/api/typography/时发生此错误,则可以通过更改元素的属性值轻松地将更<p>改为:<span>component<Typography>

<Typography component={'span'} variant={'body2'}>

根据排版文档:

component:用于根节点的组件。使用DOM元素的字符串或组件。默认情况下,它将变体映射到良好的默认标题组件。

因此,印刷术是<p>明智的默认选择,您可以更改。可能会有副作用...对我有用。


就SEO而言,这是不幸的,特别是如果您希望组件成为标头(可识别),但带有类似h4的变体。
pfeds '19

在进一步摸索中,您似乎可以拥有一个带有variant =“ inherit”的根Typography元素(即在页面级别),然后是一个子Typography组件=“ h1” variant =“ h5”。它似乎可行,但是我不能完全确定我是否以正确的方式使用Typography ...
pfeds

5
我曾经使用过<Typography component={'div'}>,现在可以正常使用而不会发出警告。非常感谢您让我走上正轨!
JohnK

我需要排版以封装div,以便我的文本正确显示在页面上。没有它作为父元素,我的css类似乎无法正确注册,对吗?但是,这就像一个魅力,注册了CSS,它消除了我的错误,亲爱的!
C.Gadd

2
这是一个实时的保护程序答案
YaakovHatam

74

根据警告消息,组件ReactTooltip呈现一个可能如下所示的HTML:

<p>
   <div>...</div>
</p>

根据该文档<p></p>标签只能包含内联元素。这意味着将<div></div>标签放入标签中应该是不合适的,因为div标签是一个块元素。不正确的嵌套可能会导致诸如渲染额外标签之类的故障,从而影响您的javascript和CSS。

如果要摆脱此警告,则可能需要自定义ReactTooltip组件,或等待创建者解决此警告。


因此,是的,我理解了呈现的内容,但是您是否会说,呈现a的任何组件div都应该重构,以便在a中使用p?面对div随意包装的东西有多么受欢迎,它似乎飞起来了?
Sander Verhagen

2
我猜是这样,因为它在w3c建议中。此外,我们可以轻松替换divspan避免这种警告,但不会影响代码的逻辑东西。
JD Hernandez

1
如果在直接使用Material UI <Typography>时收到此错误,则可以更改“组件”,我将在下面的答案中进行描述。希望这会
有所

尝试在<p>中使用<span>而不是<div>-这应该可以解决。我通过使用<div>来显示由父css类指定源的图像而遇到此错误。
Christopher Stock

18

如果您正在寻找发生这种情况的地方,可以在控制台中使用: document.querySelectorAll(" p * div ")


16

您的组件可能会在另一个组件(例如 <Typography> ... </Typography>)内。因此,它将把您的组件加载到<p> .. </p>不允许的。

修复:删除,<Typography>...</Typography>因为这仅用于a <p>...</p>或任何其他文本元素(例如标题)中的纯文本。


4
我曾经使用过<Typography component={'div'}>,现在可以正常使用而不会发出警告。非常感谢您让我走上正轨!
JohnK

8

我通过使用Material UI组件收到此警告,然后测试component="div"了以下代码的as prop,一切都正确了:

import Grid from '@material-ui/core/Grid';
import Typography from '@material-ui/core/Typography';

<Typography component="span">
  <Grid component="span">
    Lorem Ipsum
  </Grid>
</Typography>

实际上,发生此警告是因为在Material UI中,Grid组件div的默认TypographyHTML标签是ptag,而默认HTML标签是tag,所以现在发生警告,

Warning: validateDOMnesting(...): <div> cannot appear as a descendant of <p>

简而言之,Material UI有错误吗?
Ero Stefano

1
亲爱的@EroStefano,这是有意让开发人员遵循内联和块级层次结构的规则。
AmerllicA

4

我遇到了类似的问题,将组件包装在“ div”而不是“ p”中,错误消失了。


4

这是浏览器的限制。您应该在App的render方法中使用div或article或类似的东西,因为这样您就可以在其中放置任何内容。段落标签仅限于仅包含一组有限的标签(主要是用于格式化文本的标签。段落内不能有div

<p><div></div></p>

是无效的HTML。根据规范中列出的标签遗漏规则,<p>标签会被标签自动关闭<div>,从而使</p>标签没有匹配项<p>。浏览器完全有权尝试通过以下方式添加一个开放<p>标记来更正它<div>

<p></p><div></div><p></p>

你不能在<div>里面放一个<p>并从各种浏览器中获得一致的结果。为浏览器提供有效的HTML,它们的行为会更好。

你可以把<div>里面<div>虽然如此,如果您更换<p><div class="p">和风格它适当地,你可以得到你想要的东西。


1
那你怎么跟踪呢?错误正在排队
ichimaru

2

如果您使用ReactTooltip,要使警告消失,现在可以添加wrapper值为的道具span,如下所示:

<ReactTooltip wrapper="span" />

由于span是内联元素,因此不应再抱怨。


您是我最好的朋友,也是最好的。爱你。
AmerllicA

2

我是通过在React <Card.Text><Card>组件部分中使用自定义组件来获得此信息的。我的组件都不在p标签中


2

仅由于演示代码具有以下内容,才会出现警告:

function TabPanel(props) {
  const { children, value, index, ...other } = props;

  return (
    <div
      role="tabpanel"
      hidden={value !== index}
      id={`simple-tabpanel-${index}`}
      aria-labelledby={`simple-tab-${index}`}
      {...other}
    >
      {value === index && (
        <Box p={3}>  // <==NOTE P TAG HERE
          <Typography>{children}</Typography>
        </Box>
      )}
    </div>
  );
}

像这样更改它就可以了:

function TabPanel(props) {
    const {children, value, index, classes, ...other} = props;

    return (
        <div
            role="tabpanel"
            hidden={value !== index}
            id={`simple-tabpanel-${index}`}
            aria-labelledby={`simple-tab-${index}`}
            {...other}
        >
            {value === index && (
                <Container>
                    <Box>   // <== P TAG REMOVED
                        {children}
                    </Box>
                </Container>
            )}
        </div>
    );
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.