<div> не може відображатися як нащадок <p>


112

Я це бачу. Не загадка, на що він скаржиться:

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

Я автор SomeComponentі SomeOtherComponent. Але остання використовує зовнішню залежність ( 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>
  }
}

Дякую.


Відповіді:


109

Якщо ця помилка виникає під час використання інтерфейсу матеріалу <Typography> https://material-ui.com/api/typography/ , тоді ви можете легко змінити значення <p>a <span>на, змінивши значення componentатрибута <Typography>елемента:

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

Відповідно до типографіки:

компонент: компонент, що використовується для кореневого вузла. Або рядок, щоб використовувати елемент DOM, або компонент. За замовчуванням він відображає варіант із гарним компонентом заголовка за замовчуванням.

Тож типографіка вибирається <p>як розумний за замовчуванням, який ви можете змінити. Може прийти з побічними ефектами ... спрацював у мене.


Це прикро з точки зору SEO, особливо якщо ви хочете, щоб компонент був заголовком (щоб його розпізнавали), але з варіантом чогось типу h4.
pfeds

При подальшому фафлінгу, здається, ви можете мати кореневий елемент Типографіки з variant = "спадкувати" (тобто на рівні сторінки), а потім допоміжний компонент Типографіки = "h1" variant = "h5". Здається, це працює, але я не зовсім впевнений, що правильно використовую типографіку ...
pfeds

5
Я використовував, <Typography component={'div'}>і зараз це працює без попереджень. Щиро дякую, що ви поставили мене на правильний шлях!
JohnK

Мені потрібна була типографія для інкапсуляції мого div, щоб мій текст відображався правильно на сторінці. Без нього як батьківського елемента мій клас css, здається, не реєструвався правильно, дивно, правда? Однак це спрацювало як шарм, css зареєструвався, і це видалило мої помилки, солодко!
C.Gadd,

2
Це відповідь у режимі реального часу
YaakovHatam

74

На основі попереджувального повідомлення компонент ReactTooltip відображає HTML, який може виглядати так:

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

Згідно з цим документом , <p></p>тег може містити лише вбудовані елементи. Це означає, що розміщення <div></div>тегу всередині нього повинно бути неправильним, оскільки divтег є блочним елементом. Неправильне вкладання може спричинити збої, наприклад, надання додаткових тегів , що може вплинути на ваш javascript та css.

Якщо ви хочете позбутися цього попередження, ви можете налаштувати компонент ReactTooltip або почекати, поки творець виправить це попередження.


Так, так, я зрозумів, що було відображено, але чи могли б ви тоді сказати, що будь-які компоненти, які відображають a, divповинні бути реконструйовані, з можливістю використання в a p? Здається, це стикається з тим, наскільки популярними були divs для довільного обгортання речей?
Сандер Верхаген,

2
Думаю, що так, оскільки це в рекомендації w3c. Крім того, ми могли б легко замінити a divна, spanщоб уникнути такого роду попередження, але не впливаючи ні на що в логіці коду.
Дж. Д. Ернандес,

1
Якщо ви отримуєте цю помилку під час безпосереднього використання інтерфейсу матеріалу <Типографія>, ви можете змінити "компонент", який я описую нижче у своїй відповіді. Сподіваюся, це допомагає
zayquan

Спробуйте використовувати <span> замість <div> всередині вашого <p> - Це має виправити це. Я зіткнувся з цією помилкою, використовуючи <div> для відображення зображення, джерелом якого є батьківський клас css.
Крістофер Сток,

18

Якщо ви шукаєте, де це відбувається, у консолі ви можете використовувати: document.querySelectorAll(" p * div ")


16

Ваш компонент може бути відображений всередині іншого компонента (наприклад, a <Typography> ... </Typography>). Отже, він буде завантажувати ваш компонент всередині, <p> .. </p>що заборонено.

Виправлення: Видалити, <Typography>...</Typography>оскільки це використовується лише для простого тексту всередині <p>...</p>або будь-якого іншого текстового елемента, наприклад заголовків.


4
Я використовував, <Typography component={'div'}>і зараз це працює без попереджень. Щиро дякую, що ви поставили мене на правильний шлях!
JohnK

8

Я отримав це застереження за допомогою компонентів 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 за замовчуванням HTML-тегом Gridкомпонента є divтег, а TypographyHTML-тегом за замовчуванням є pтег, отже, тепер попередження трапляється,

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

Коротко кажучи Матеріальний інтерфейс має помилки?
Еро Стефано,

1
Ніякий дорогий @EroStefano, це навмисне, щоб розробник дотримувався правила ієрархії вбудованого та блокового рівнів.
AmerllicA

4

У мене була подібна проблема, і я загорнув компонент у "div" замість "p", і помилка зникла.


4

Це обмеження браузерів. Ви повинні використовувати div або article або щось подібне в методі візуалізації App, оскільки таким чином ви можете помістити все, що вам подобається, всередину цього. Теги абзацу обмежуються лише тим, що містять обмежений набір тегів (переважно теги для форматування тексту. Ви не можете мати div всередині абзацу

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

недійсний HTML. Відповідно до правил пропуску тегів, перелічених у специфікації, <p>тег автоматично закривається <div>тегом, що залишає </p>тег без відповідності <p>. Браузер в межах своїх прав намагається виправити його, додавши відкритий <p>тег після <div>:

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

Ви не можете помістити <div>всередину a <p>і отримати постійні результати від різних браузерів. Надайте браузерам дійсний HTML, і вони будуть поводитися краще.

Ви можете помістити <div>всередину, <div>хоча, якщо ви заміните свій <p>на <div class="p">і правильно його оформите, ви зможете отримати те, що хочете.


1
так як ви це відстежуєте? помилки шикуються
Ічімару,

2

Якщо ви використовуєте ReactTooltip, щоб попередження зникло, тепер ви можете додати wrapperреквізит зі значенням span, наприклад:

<ReactTooltip wrapper="span" />

Оскільки spanелемент є вбудованим елементом, він більше не повинен скаржитися.


Ти найкращий мій друже, найкращий з найкращих. Люблю тебе.
Amerllic,

2

Я отримав це завдяки використанню користувацького компонента всередині <Card.Text>розділу <Card>компонента в React. Жоден з моїх компонентів не містився в тегах p


2

Попередження з'являється лише тому, що демо-код містить:

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>
    );
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.