<div> nie może występować jako potomek <p>

125

Widzę to. Nie jest tajemnicą, na co narzeka:

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

Jestem autorem SomeComponenti SomeOtherComponent. Ale ta ostatnia używa zależności zewnętrznej ( ReactTooltipz react-tooltip). Prawdopodobnie nie jest istotne, że jest to zależność zewnętrzna, ale pozwala mi wypróbować argument, że jest to „jakiś kod, który jest poza moją kontrolą”.

Jak bardzo powinienem się martwić tym ostrzeżeniem, biorąc pod uwagę, że zagnieżdżony komponent działa dobrze (pozornie)? Jak i tak bym to zmienił (pod warunkiem, że nie chcę ponownie wdrażać zewnętrznej zależności)? Czy jest może lepszy projekt, o którym jeszcze nie wiem?

Ze względu na kompletność oto implementacja SomeOtherComponent. Po prostu się renderuje this.props.value, a po najechaniu kursorem: podpowiedź z informacją „Jakaś podpowiedź”:

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

Dziękuję Ci.

Sander Verhagen
źródło
1
Powiązany problem: github.com/wwayne/react-tooltip/issues/210
Jordan Bieganie

Odpowiedzi:

121

Jeśli ten błąd wystąpi podczas korzystania z Material UI <Typography> https://material-ui.com/api/typography/ , możesz łatwo zmienić na <p>a <span>, zmieniając wartość componentatrybutu <Typography>elementu:

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

Zgodnie z dokumentacją typograficzną:

komponent: komponent używany dla węzła głównego. Ciąg znaków używany do użycia elementu DOM lub komponentu. Domyślnie odwzorowuje wariant na dobry domyślny składnik nagłówka.

Dlatego typografia jest wybierana <p>jako rozsądna opcja domyślna, którą można zmienić. Może przynieść efekty uboczne ... zadziałało dla mnie.

zayquan
źródło
Jest to niefortunne z punktu widzenia SEO, zwłaszcza jeśli chcesz, aby komponent był nagłówkiem (aby był rozpoznawany), ale z wariantem czegoś takiego jak h4.
pfeds
Przy dalszym rozwiązywaniu problemów wydaje się, że możesz mieć główny element Typography z variant = "inherit" (tj. Na poziomie strony), a następnie podrzędny komponent Typography = "h1" variant = "h5". Wydaje się, że działa, ale nie jestem do końca pewien, czy używam Typografii we właściwy sposób ...
pfeds
7
Używałem <Typography component={'div'}>i teraz działa bez ostrzeżeń. Dziękuję bardzo za skierowanie mnie na właściwą drogę!
JohnK,
Potrzebowałem typografii do hermetyzacji mojego div, aby mój tekst był poprawnie wyświetlany na stronie. Bez niego jako elementu nadrzędnego moja klasa css nie rejestrowała się poprawnie, dziwne, prawda? Jednak zadziałało to cudownie, css zarejestrował się i usunęło moje błędy, kochanie!
C.Gadd
5
To oszczędza czas w czasie rzeczywistym
YaakovHatam
78

Na podstawie komunikatu ostrzegawczego komponent ReactTooltip renderuje kod HTML, który może wyglądać następująco:

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

Według tego dokumentu , wykorzystując <p></p>znacznik może zawierać tylko elementy liniowe. Oznacza to, że umieszczenie w nim <div></div>tagu powinno być niewłaściwe, ponieważ divtag jest elementem blokowym. Niewłaściwe zagnieżdżanie może powodować usterki, takie jak renderowanie dodatkowych tagów , które mogą wpływać na JavaScript i css.

Jeśli chcesz pozbyć się tego ostrzeżenia, możesz dostosować komponent ReactTooltip lub poczekać, aż twórca naprawi to ostrzeżenie.

JD Hernandez
źródło
Więc tak, rozumiem, co zostało wyrenderowane, ale czy możesz powiedzieć, że jakiekolwiek komponenty renderujące a divpowinny zostać refaktoryzowane, jeśli mają szansę zostać użyte w p? Wydaje się, że jest to sprzeczne z tym, jak bardzo popularne divjest dowolne pakowanie rzeczy?
Sander Verhagen
2
Chyba tak, ponieważ jest to w zaleceniu w3c. Moglibyśmy również łatwo zamienić a na diva, spanaby uniknąć tego rodzaju ostrzeżeń, ale bez wpływu na logikę kodu.
JD Hernandez
1
Jeśli otrzymujesz ten błąd podczas bezpośredniego korzystania z Material UI <Typography>, możesz zmienić „komponent”, który opisuję poniżej w mojej odpowiedzi. Mam nadzieję, że to pomoże
zayquan
Spróbuj użyć <span> zamiast <div> w swoim <p> - To powinno rozwiązać problem. Napotkałem ten błąd, używając <div> do wyświetlania obrazu, którego źródło jest określone przez nadrzędną klasę css.
Christopher Stock
21

Jeśli szukasz, gdzie to się dzieje, w konsoli możesz użyć: document.querySelectorAll(" p * div ")

Alex C
źródło
17

Twój komponent może być renderowany wewnątrz innego komponentu (na przykład a <Typography> ... </Typography>). Dlatego załaduje twój komponent do wnętrza, <p> .. </p>co jest niedozwolone.

Poprawka: usuń, <Typography>...</Typography>ponieważ jest to używane tylko w przypadku zwykłego tekstu wewnątrz <p>...</p>lub dowolnego innego elementu tekstowego, takiego jak nagłówki.

Dion Duimel
źródło
4
Używałem <Typography component={'div'}>i teraz działa bez ostrzeżeń. Dziękuję bardzo za skierowanie mnie na właściwą drogę!
JohnK,
11

Otrzymałem to ostrzeżenie, używając komponentów Material UI , następnie component="div"testuję as prop do poniższego kodu i wszystko stało się poprawne:

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

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

W rzeczywistości to ostrzeżenie występuje, ponieważ w interfejsie Material domyślnym znacznikiem HTML Gridkomponentu jest divtag, a domyślnym Typographyznacznikiem HTML jest ptag, więc teraz pojawia się ostrzeżenie,

Warning: validateDOMnesting(...): <div> cannot appear as a descendant of <p>
AmerllicA
źródło
Krótko mówiąc, Material UI zawiera błędy?
Ero Stefano
1
Nie, drogi @EroStefano, jest to celowe, że programista postępuje zgodnie z zasadą hierarchii poziomów inline i block.
AmerllicA
6

To jest ograniczenie przeglądarek. Powinieneś użyć div, article lub czegoś podobnego w metodzie renderowania aplikacji, ponieważ w ten sposób możesz umieścić w nim wszystko, co chcesz. Tagi akapitu mogą zawierać tylko ograniczony zestaw tagów (głównie znaczniki do formatowania tekstu. W akapicie nie można umieścić elementu div

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

nie jest prawidłowym kodem HTML. Zgodnie z regułami pomijania tagów wymienionymi w specyfikacji, <p>tag jest automatycznie zamykany przez <div>tag, który pozostawia </p>tag bez dopasowania <p>. Przeglądarka ma pełne prawo podjąć próbę poprawienia tego problemu przez dodanie otwartego <p>tagu po <div>:

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

Nie możesz umieścić <div>wewnątrz a <p>i uzyskać spójnych wyników z różnych przeglądarek. Zapewnij przeglądarkom prawidłowy kod HTML, a będą się lepiej zachowywać.

Możesz umieścić w <div>środku <div>choć, więc jeśli zastąpisz <p>go <div class="p">i odpowiednio go ułożysz , możesz dostać to, co chcesz.

jithu
źródło
1
więc jak to śledzisz? błędy się ustawiają
ichimaru
6

Ostrzeżenie pojawia się tylko dlatego, że kod demo zawiera:

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

Zmiana tego w ten sposób zajmie się tym:

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>
    );
}
VikR
źródło
1
Niech cię Bóg błogosławi. Zmarnowałem tyle czasu na sprawdzanie własnych komponentów
M. Dada
4

Miałem podobny problem i umieściłem komponent w „div” zamiast „p”, a błąd zniknął.

jbluft
źródło
2

Jeśli używasz ReactTooltip, aby usunąć ostrzeżenie, możesz teraz dodać wrapperwłaściwość o wartości span, na przykład:

<ReactTooltip wrapper="span" />

Ponieważ spanjest to element wbudowany, nie powinien już narzekać.

Nicco
źródło
Jesteś najlepszym przyjacielem, najlepszym z najlepszych. Kocham Cię.
AmerllicA
2

Otrzymałem to dzięki użyciu niestandardowego komponentu wewnątrz <Card.Text>sekcji <Card>komponentu w Reakcie. Żaden z moich składników nie był w znacznikach p

BitShift
źródło
-1

błąd, który otrzymuję

 <p>
  <UserList userId={post.id} />
 </p>

pokazuje Warning: validateDOMNesting(...): <div> cannot appear as a descendant of <p>ten błąd, ponieważ wewnątrz UserList jest <div>UserList</div> tak źle

- Standardowo możemy wywołać p lub dowolny tag wewnątrz div

- Ale w moim przypadku nazywam div wewnątrz p, więc pojawia się błąd

powinno być

   <div>
      <UserList userId={post.id} />
     </div>
Naved Khan
źródło