【问题标题】:<div> cannot appear as a descendant of <p><div> 不能作为 <p> 的后代出现
【发布时间】:2017-06-15 04:15:00
【问题描述】:

我看到了。它在抱怨什么并不神秘:

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

我是SomeComponentSomeOtherComponent 的作者。但后者使用的是外部依赖(ReactTooltip 来自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>
  }
}

谢谢。

【问题讨论】:

标签: javascript reactjs


【解决方案1】:

如果在使用 Material UI &lt;Typography&gt;https://material-ui.com/api/typography/ 时出现此错误,那么您可以通过更改 &lt;Typography&gt; 元素的 component 属性的值轻松地将 &lt;p&gt; 更改为 &lt;span&gt;

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

根据排版文档:

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

所以 Typography 选择 &lt;p&gt; 作为合理的默认值,您可以更改它。可能会带来副作用......对我有用。

【讨论】:

  • 在 SEO 方面是不幸的,特别是如果您希望组件成为标题(被识别),但具有类似 h4 的变体。
  • 在进一步的讨论中,您似乎可以拥有一个带有 variant="inherit" 的根 Typography 元素(即在页面级别),然后是一个子 Typography component="h1" variant="h5" .它似乎有效,但我不完全确定我是否以正确的方式使用排版......
  • 我使用了&lt;Typography component={'div'}&gt;,它现在可以在没有警告的情况下运行。非常感谢你让我走上正轨!
  • 我需要一个排版来封装我的 div,以便我的文本在页面上正确显示。如果没有它作为父元素,我的 css 类似乎没有正确注册,很奇怪吧?然而,这就像一个魅力,注册的 css 并消除了我的错误,亲爱的!
【解决方案2】:

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

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

根据这个document&lt;p&gt;&lt;/p&gt; 标签只能包含内联元素。这意味着在其中放置&lt;div&gt;&lt;/div&gt; 标签应该是不合适的,因为div 标签是一个块元素。不正确的嵌套可能会导致渲染extra tags 等故障,这会影响您的 javascript 和 css。

如果你想摆脱这个警告,你可能需要自定义 ReactTooltip 组件,或者等待创建者修复这个警告。

【讨论】:

  • 所以,是的,我理解了渲染的内容,但是您是否会说任何渲染 div 的组件都应该重构,以便在 p 中使用?面对divs 任意包装东西的受欢迎程度,它似乎飞了起来?
  • 我猜是这样,因为它在 w3c 推荐中。此外,我们可以轻松地将 div 替换为 span 以避免此类警告,但不会影响代码逻辑中的任何内容。
  • 如果您在直接使用 Material UI 时遇到此错误,您可以更改“组件”,我在下面的回答中对此进行了描述。希望这会有所帮助
  • 尝试在

    中使用 而不是

    - 这应该可以解决问题。我通过使用
    来显示由父 css 类指定的源图像时遇到了这个错误。

【解决方案3】:

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

【讨论】:

  • 这是另一个版本,让我找到该项目更加冗长document.querySelectorAll("p &gt; div")
【解决方案4】:

您的组件可能会在另一个组件中呈现(例如&lt;Typography&gt; ... &lt;/Typography&gt;)。因此,它会将您的组件加载到 &lt;p&gt; .. &lt;/p&gt; 中,这是不允许的。

修复: 删除&lt;Typography&gt;...&lt;/Typography&gt;,因为这仅用于&lt;p&gt;...&lt;/p&gt; 内的纯文本或任何其他文本元素,例如标题。

【讨论】:

  • 我使用了&lt;Typography component={'div'}&gt;,它现在可以在没有警告的情况下工作。非常感谢你让我走上正轨!
【解决方案5】:

我通过使用Material UI 组件得到了这个警告,然后我测试了component="div" 作为下面代码的支柱,一切都变得正确:

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 组件的默认 HTML 标签是 div 标签,而默认的Typography HTML 标签是 p 标签,所以现在出现了警告,

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

详细信息 (以及一些关于警告的 HTML 理论) 显示 &lt;div&gt; cannot appear as a descendant of &lt;p&gt; 消息是因为 @987654332 &lt;p&gt; 标签的 @ 符合为 Phrasing Context 设置的标准,其中不包括 &lt;div&gt; 标签。有关详细信息,请参阅链接。

【讨论】:

  • 简而言之,Material UI 有 bug?
  • 不,亲爱的@EroStefano,这是有意让开发人员遵循内联和块级别的层次结构规则。
  • @KostasX,感谢您的精彩版本。
【解决方案6】:

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

&lt;p&gt;&lt;div&gt;&lt;/div&gt;&lt;/p&gt;

不是有效的 HTML。根据规范中列出的标签省略规则,&lt;p&gt; 标签会自动被&lt;div&gt; 标签关闭,这使得&lt;/p&gt; 标签没有匹配的&lt;p&gt;。浏览器完全有权通过在&lt;div&gt; 之后添加打开的&lt;p&gt; 标记来尝试更正它:

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

您不能将&lt;div&gt; 放在&lt;p&gt; 中并从各种浏览器中获得一致的结果。为浏览器提供有效的 HTML,它们会表现得更好。

您可以将&lt;div&gt; 放在&lt;div&gt; 中,因此如果您将&lt;p&gt; 替换为&lt;div class="p"&gt; 并适当地设置它的样式,您就可以获得您想要的。


详细信息 (以及一些关于警告的 HTML 理论) 显示 &lt;div&gt; cannot appear as a descendant of &lt;p&gt; 消息是因为 @987654338 &lt;p&gt; 标签的 @ 符合为 Phrasing Context 设置的标准,其中不包括 &lt;div&gt; 标签。有关详细信息,请参阅链接。

【讨论】:

  • 那么你如何跟踪这个?错误正在排列
【解决方案7】:

警告出现只是因为演示代码有:

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>
    );
}

【讨论】:

  • 很好奇——Box 组件的 p={3} 参数与填充有关,对吧?虽然该错误确实与浏览器的约束有关——因此段落标签内的 div 被认为是无效的——@jithu 清楚地回答了。为了解决这个问题 - 删除 组件以防止默认情况下将内容包装在

    内。

【解决方案8】:

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

【讨论】:

    【解决方案9】:

    我是通过在 React 中使用组件的 react-boostrap &lt;Card.Text&gt; 部分得到的。我的组件都没有在 p 标签中。 默认显示为

    在 HTML 树中一旦渲染并且基本上有一个自定义的 React 组件在 &lt;div&gt; it 中返回它的 jsx 元素,它会导致 &lt;p&gt;&lt;div&gt;...&lt;/div&gt;&lt;/p&gt; 这是一个糟糕的 HTML。因此,如果使用 要解决此问题,您基本上可以使用 'as' 属性,如下所示 &lt;Card.Text as='div'&gt; 这将解决警告,因为它允许像 &lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt; 这样的树

    【讨论】:

      【解决方案10】:

      我是通过在 React 中 &lt;Card&gt; 组件的 &lt;Card.Text&gt; 部分中使用自定义组件得到的。我的组件都没有在 p 标签中

      【讨论】:

        【解决方案11】:

        如果您使用ReactTooltip,为了使警告消失,您现在可以添加一个值为spanwrapper 属性,如下所示:

        <ReactTooltip wrapper="span" />
        

        由于span 是一个内联元素,它不应该再抱怨了。

        【讨论】:

          【解决方案12】:

          我在 React 中使用 Chakra UI 为某些文本进行内联样式时遇到此错误。进行内联样式的正确方法是使用 span 元素,正如其他人对其他样式框架所说的那样。正确代码:

          <Text as="span" fontWeight="bold">
              Bold text
              <Text display="inline" fontWeight="normal">normal inline text</Text>
          </Text>
          

          【讨论】:

            【解决方案13】:

            我迟到了。这个错误也发生在我身上,它发生的原因是因为我使用了反应材料 TAB。因为我们使用了类似的东西,然后我们将孩子道具包裹在 {children} 中。它发生的原因是因为反应不这么认为,用它来代替它。

            【讨论】:

              【解决方案14】:

              App.js 在渲染过程中出现问题。 Don't use &lt;div&gt;...&lt;/div&gt; to render just use &lt;&gt;...&lt;/&gt;.

              【讨论】:

                猜你喜欢
                • 2019-02-15
                • 1970-01-01
                • 2019-01-02
                • 2021-10-25
                • 2020-08-04
                • 1970-01-01
                • 2021-05-30
                • 2019-04-30
                • 2019-09-01
                相关资源
                最近更新 更多