<div>不能作为<p>的后代出现

时间:2017-01-30 03:16:39

标签: reactjs

我看到了这个。它抱怨的内容并不神秘:

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

我是SomeComponentSomeOtherComponent的作者。但后者使用外部依赖(react-tooltip来自ReactTooltip)。这可能不是必需的,这是一个外部依赖,但它让我尝试这里的论点,它是“一些不受我控制的代码”。

考虑到嵌套组件工作正常(貌似),我对这个警告有多担心?无论如何我都会如何改变它(假设我不想重新实现外部依赖)?是否有更好的设计,我还没有意识到?

为了完整起见,这里是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>
  }
}

谢谢。

12 个答案:

答案 0 :(得分:42)

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

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

根据此document<p></p>标记只能包含内联元素。这意味着在其中放置<div></div>标记应该是不正确的,因为div标记是一个块元素。不正确的嵌套可能会导致渲染extra tags等毛刺,这可能会影响您的javascript和css。

如果您想要摆脱此警告,您可能希望自定义ReactTooltip组件,或等待创建者修复此警告。

答案 1 :(得分:26)

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

<Typography>

根据排版文档:

  

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

因此,印刷术选择<Typography component={'span'} variant={'body2'}> 作为明智的默认设置,可以更改。可能会有副作用...对我有用。

答案 2 :(得分:11)

我通过使用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>

答案 3 :(得分:7)

这是浏览器的约束。您应该在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">并对其进行适当样式设置,则可以得到想要的东西。

答案 4 :(得分:6)

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

library(dplyr)
df1 %>% 
   group_by(Feature) %>%
   filter(n == max(n)) %>% 
   summarise(priority = if(n() >1 & 
           all(c("high", "low") %in% priority)) "medium" else priority)
# A tibble: 5 x 2
#  Feature priority
#  <chr>   <chr>   
#1 goofy   high    
#2 happy   high    
#3 mad     low     
#4 sad     high    
#5 worry   medium  

像这样更改它就可以了:

df1 <- structure(list(Feature = c("happy", "happy", "sad", "sad", "goofy", 
"mad", "mad", "worry", "worry"), priority = c("low", "high", 
"low", "high", "high", "low", "high", "high", "low"), n = c(2L, 
5L, 7L, 10L, 2L, 4L, 3L, 5L, 5L)), class = "data.frame", row.names = c(NA, 
-9L))

答案 5 :(得分:5)

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

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

答案 6 :(得分:4)

我是通过在 React 中使用一个组件的 react-boostrap <Card.Text> 部分得到的。我的组件都没有在 p 标签中。 默认在 HTML 树中显示为

一旦呈现,并且基本上有一个自定义 React 组件在 <div> 中返回其 jsx 元素,这会导致 <p><div>...</div></p>这是一个糟糕的 HTML。因此,如果使用 来解决此问题,您基本上可以使用 'as' 属性如下 <Card.Text as='div'> 这将解决警告,因为它允许诸如 <div><div></div></div>

之类的树

答案 7 :(得分:2)

我有一个类似的问题,并将组件包装在&#34; div&#34;而不是&#34; p&#34;并且错误消失了。

答案 8 :(得分:2)

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

答案 9 :(得分:2)

如果您使用ReactTooltip来使警告消失,则现在可以添加一个值为wrapper的{​​{1}}道具,如下所示:

span

由于<ReactTooltip wrapper="span" /> 是内联元素,因此不再抱怨。

答案 10 :(得分:1)

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

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

答案 11 :(得分:0)

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