Pesquisa de site

javascript - <div> não pode aparecer como descendente de


Estou vendo isso. Não é um mistério sobre o que ele está reclamando:

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

Sou o autor de SomeComponent e SomeOtherComponent. Mas este último está usando uma dependência externa (ReactTooltip do react-tooltip). Provavelmente não é essencial que isso seja uma dependência externa, mas me permite levantar aqui o argumento de que é "algum código que está fora do meu controle".

Quão preocupado eu devo ficar com esse aviso, dado que o componente aninhado está funcionando muito bem (aparentemente)? E como eu deveria proceder para mudar isso de qualquer forma (considerando que eu não quero reimplementar uma dependência externa)? Existe talvez um design melhor do qual eu ainda não estou ciente?

Para maior completude, aqui está a implementação de SomeOtherComponent. Ele apenas renderiza this.props.value, e quando o mouse passa por cima: um tooltip que diz "Some tooltip message":

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

Obrigado.

Resposta #1

Se esse erro ocorrer ao usar o Material UI <Typography> https://material-ui.com/api/typography/, então você pode facilmente mudar o <p> para um <span> alterando o valor do atributo component do elemento <Typography> :

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

De acordo com os documentos de tipografia:

componente: O componente usado para o nó raiz. Pode ser uma string para usar um elemento DOM ou um componente. Por padrão, ele mapeia a variante para um bom componente de título padrão.

Então, a Tipografia está escolhendo <p> como um padrão sensato, que você pode mudar. Pode vir com efeitos colaterais ... funcionou para mim.

Resposta #2

Com base na mensagem de aviso, o componente ReactTooltip renderiza um HTML que pode se parecer com isto:

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

De acordo com este documento, uma tag <p></p> só pode conter elementos inline. Isso significa que colocar uma tag <div></div> dentro dela deve ser inadequado, uma vez que a tag div é um elemento de bloco. Aninhamento inadequado pode causar falhas como a renderização de tags extras, o que pode afetar seu javascript e css.

Se você quiser se livrar deste aviso, talvez queira personalizar o componente ReactTooltip, ou esperar que o criador corrija este aviso.

Resposta #3

Se você está procurando onde isso está acontecendo, no console você pode usar: document.querySelectorAll(" p * div ")

Resposta #4

Recebi este aviso ao usar os componentes do Material UI, então testei o component="div" como prop no código abaixo e tudo ficou correto:

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

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

Na verdade, este aviso acontece porque no Material UI a tag HTML padrão do componente Grid é a tag div e a tag HTML padrão do Typography é a tag p. Então, agora o aviso acontece,

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

Detalhes (e alguma teoria de HTML sobre o aviso) : A mensagem <div> não pode aparecer como descendente de <p> é exibida devido ao fato de que o conteúdo permitido de uma tag <p> é, de acordo com os padrões, definido para o Contexto de Frase, que não inclui tags <div>. Veja os links para mais detalhes.

Resposta #5

Seu componente pode ser renderizado dentro de outro componente (como um <Typography> ... </Typography>). Portanto, ele carregará seu componente dentro de um <p> .. </p>, o que não é permitido.

Correção: Remova <Typography>...</Typography> porque isso é usado apenas para texto simples dentro de um <p>...</p> ou qualquer outro elemento de texto, como títulos.

Resposta #6

Esta é uma limitação dos navegadores. Você deve usar div ou article ou algo assim no método render do App, porque dessa forma você pode colocar o que quiser dentro dele. As tags de parágrafo são limitadas a conter apenas um conjunto limitado de tags (principalmente tags para formatação de texto). Você não pode ter uma div dentro de um parágrafo.

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

não é HTML válido. De acordo com as regras de omissão de tags listadas na especificação, a tag <p> é automaticamente fechada pela tag <div>, o que deixa a tag </p> sem uma <p> correspondente. O navegador está totalmente dentro de seus direitos de tentar corrigir isso adicionando uma tag <p> aberta após a <div>:

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

Você não pode colocar um <div> dentro de um <p> e obter resultados consistentes em vários navegadores. Forneça aos navegadores HTML válido e eles irão se comportar melhor.

Você pode colocar <div> dentro de um <div>, então se você substituir seu <p> por <div class="p"> e estilizar adequadamente, você pode conseguir o que deseja.


Detalhes (e alguma teoria HTML sobre o aviso): A mensagem <div> não pode aparecer como descendente da mensagem <p> é mostrada devido ao fato de que o conteúdo permitido de uma tag <p> está de acordo com os padrões estabelecidos para o Contexto de Fraseamento, que não inclui tags <div>. Veja os links para mais detalhes.

Resposta #7

Com Material UI !!!!!

Passei uma quantidade embaraçosa de tempo, mas graças a esta resposta --> aqui por Alex C, que deu esta solução muito simples, mas inteligente

document.querySelectorAll(" p * div ")

Então, para minha surpresa, foi o componente Material UI DialogContentText DialogContentText API que causou o problema

Então, basta usar component={'span'} para resolver o problema (isso não afetará o estilo)

 <DialogContentText id="alert-dialog-inputs" component={'span'}/>

Resposta #8

O aviso aparece apenas porque o código de demonstração tem:

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

Alterar assim resolve:

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

Artigos relacionados