<div> ne peut pas apparaître comme un descendant de <p>


112

Je vois ça. Ce dont il se plaint n'est pas un mystère:

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

Je suis l'auteur de SomeComponentet SomeOtherComponent. Mais ce dernier utilise une dépendance externe ( ReactTooltipde react-tooltip). Il n'est probablement pas essentiel qu'il s'agisse d'une dépendance externe, mais cela me permet d'essayer l'argument ici selon lequel il s'agit d'un "code hors de mon contrôle".

Dans quelle mesure devrais-je m'inquiéter de cet avertissement, étant donné que le composant imbriqué fonctionne très bien (en apparence)? Et comment pourrais-je changer cela de toute façon (à condition que je ne souhaite pas réimplémenter une dépendance externe)? Y a-t-il peut-être un meilleur design que je ne connais pas encore?

Par souci d'exhaustivité, voici l'implémentation de SomeOtherComponent. Il rend juste this.props.value, et lorsqu'il est survolé: une info-bulle qui dit "Un message d'info-bulle":

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

Je vous remercie.


Réponses:


110

Si cette erreur se produit lors de l'utilisation de Material UI <Typography> https://material-ui.com/api/typography/ , vous pouvez facilement changer le <p>en un <span>en modifiant la valeur de l' componentattribut de l' <Typography>élément:

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

Selon la documentation sur la typographie:

composant: le composant utilisé pour le nœud racine. Soit une chaîne pour utiliser un élément DOM, soit un composant. Par défaut, il mappe la variante à un bon composant de titre par défaut.

La typographie choisit donc <p>comme valeur par défaut raisonnable, que vous pouvez modifier. Peut venir avec des effets secondaires ... a fonctionné pour moi.


C'est malheureux en termes de référencement, surtout si vous voulez que le composant soit un en-tête (pour être reconnu), mais avec une variante de quelque chose comme h4.
pfeds

Plus loin, il semble que vous puissiez avoir un élément de typographie racine avec variant = "inherit" (c'est-à-dire au niveau de la page), puis un sous-composant de typographie = "h1" variant = "h5". Cela semble fonctionner, mais je ne suis pas tout à fait sûr d'utiliser la typographie de la bonne manière ...
pfeds

5
Je l'ai utilisé <Typography component={'div'}>et cela fonctionne sans avertissements maintenant. Merci beaucoup de m'avoir mis sur la bonne voie!
JohnK

J'avais besoin d'une typographie pour encapsuler mon div afin que mon texte s'affiche correctement sur la page. Sans lui comme élément parent, ma classe css ne semblait pas s'enregistrer correctement, étrange non? Cependant, cela a fonctionné comme un charme, le css s'est enregistré et cela a supprimé mes erreurs, ma douce!
C.Gadd

2
Ceci est une réponse qui permet d'économiser du temps réel
YaakovHatam

74

Sur la base du message d'avertissement, le composant ReactTooltip rend un HTML qui pourrait ressembler à ceci:

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

Selon ce document , une <p></p>balise ne peut contenir que des éléments en ligne. Cela signifie que l'insertion d'une <div></div>balise à l'intérieur ne devrait pas être appropriée, car la divbalise est un élément de bloc. Une imbrication incorrecte peut provoquer des problèmes tels que le rendu de balises supplémentaires , ce qui peut affecter votre javascript et votre css.

Si vous souhaitez supprimer cet avertissement, vous souhaiterez peut-être personnaliser le composant ReactTooltip ou attendre que le créateur corrige cet avertissement.


Donc, oui, j'ai compris ce qui a été rendu, mais diriez-vous alors que tous les composants qui rendent un divdevraient être refactorisés, sur la possibilité d'être utilisés dans un p? Cela semble aller à l'encontre de la popularité des divs pour emballer arbitrairement des choses?
Sander Verhagen

2
Je suppose que oui, car c'est dans la recommandation du w3c. Aussi, on pourrait facilement remplacer a divpar a spanpour éviter ce genre d'avertissement mais sans rien affecter dans la logique du code.
JD Hernandez

1
Si vous obtenez cette erreur lors de l'utilisation de Material UI <Typography> directement, vous pouvez modifier le "composant", que je décris ci-dessous dans ma réponse. J'espère que cela aide
zayquan

Essayez d'utiliser <span> au lieu de <div> dans votre <p> - Cela devrait résoudre le problème. J'ai rencontré cette erreur en utilisant <div> pour afficher une image dont la source est spécifiée par une classe css parent.
Christopher Stock

18

Si vous cherchez où cela se produit, dans la console, vous pouvez utiliser: document.querySelectorAll(" p * div ")


16

Votre composant peut être rendu dans un autre composant (tel qu'un <Typography> ... </Typography> ). Par conséquent, il chargera votre composant à l'intérieur d'un <p> .. </p>ce qui n'est pas autorisé.

Correction: supprimez <Typography>...</Typography>car cela n'est utilisé que pour le texte brut à l'intérieur d'un <p>...</p>ou de tout autre élément de texte tel que les en-têtes.


4
Je l'ai utilisé <Typography component={'div'}>et cela fonctionne sans avertissements maintenant. Merci beaucoup de m'avoir mis sur la bonne voie!
JohnK

8

J'ai reçu cet avertissement en utilisant les composants de l' interface utilisateur matérielle, puis je teste l' component="div"as prop avec le code ci-dessous et tout est devenu correct:

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

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

En fait, cet avertissement se produit car dans l'interface utilisateur du matériau, la balise HTML par défaut du Gridcomposant est divbalise et la Typographybalise HTML par défaut est pbalise, donc maintenant l'avertissement se produit,

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

En bref, Material UI a des bugs?
Ero Stefano

1
Non cher @EroStefano, c'est intentionnel que le développeur suive la règle de la hiérarchie des niveaux en ligne et en bloc.
AmerllicA

4

J'ai eu un problème similaire et j'ai enveloppé le composant dans "div" au lieu de "p" et l'erreur a disparu.


4

C'est une contrainte des navigateurs. Vous devriez utiliser div ou article ou quelque chose comme ça dans la méthode de rendu de App car de cette façon, vous pouvez y mettre tout ce que vous voulez. Les balises de paragraphe sont limitées à ne contenir qu'un ensemble limité de balises (principalement des balises pour la mise en forme du texte. Vous ne pouvez pas avoir de div à l'intérieur d'un paragraphe.

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

n'est pas du HTML valide. Selon les règles d'omission de balise répertoriées dans la spécification, la <p>balise est automatiquement fermée par la <div>balise, ce qui laisse la </p>balise sans correspondance <p>. Le navigateur a tout à fait le droit de tenter de le corriger en ajoutant une <p>balise ouverte après le <div>:

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

Vous ne pouvez pas mettre un à l' <div>intérieur d'un<p> et obtenir des résultats cohérents à partir de différents navigateurs. Fournissez aux navigateurs un code HTML valide et ils se comporteront mieux.

Vous pouvez mettre à l' <div>intérieur un <div>si vous remplacez votre <p>par <div class="p">et le stylisez de manière appropriée, vous pouvez obtenir ce que vous voulez.


1
alors comment suivez-vous cela? les erreurs s'alignent
ichimaru le

2

Si vous utilisez ReactTooltip, pour faire disparaître l'avertissement, vous pouvez maintenant ajouter un wrapperaccessoire avec une valeur de span, comme ceci:

<ReactTooltip wrapper="span" />

Puisque le spanest un élément en ligne, il ne devrait plus se plaindre.


Tu es le meilleur mon ami, le meilleur des meilleurs. Je t'aime.
AmerllicA

2

J'ai obtenu cela en utilisant un composant personnalisé dans une <Card.Text>section d'un <Card>composant dans React. Aucun de mes composants n'était dans les balises p


2

L'avertissement apparaît uniquement parce que le code de démonstration a:

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

Le changer comme ça s'en occupe:

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>
    );
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.