React: Неожиданное предупреждение при увлажнении с помощью портала и SSR

Созданный на 15 апр. 2018  ·  24Комментарии  ·  Источник: facebook/react

Вы хотите запросить функцию или сообщить об ошибке ?

ошибка

Каково текущее поведение?

Учитывая следующий (упрощенный) фрагмент:

class HoverMenu extends React.Component {
  render() {
    if (typeof document === 'undefined') return null
    const root = document.getElementById('root')
    return ReactDOM.createPortal(<div>Hello World</div>, root)
  }
}

class Para extends React.Component {
  render() {
    return (
      <span>
        Some Text
        <HoverMenu />
      </span>
    )
  }
} 

где div#root - действительный существующий div , при гидратации после SSR отображается следующая ошибка:

Warning: Expected server HTML to contain a matching <div> in <span>

Предупреждение исчезнет, ​​если я обновлю определение HoverMenu до:

class HoverMenu extends React.Component {
  componentDidMount() {
    this.setState({ isActive: true })
  }
  render() {
    const { isActive} = this.state
    if (!isActive) return null
    const root = document.getElementById('root')
    return ReactDOM.createPortal(<div>Hello World</div>, root)
  }
}

Я бы предпочел не делать этого из-за двойного рендеринга, вызванного setState в componentDidMount .

Я не совсем понимаю, о чем мне говорит эта ошибка. В любом случае <div /> не отображается на стороне сервера. Ошибка особенно сбивает с толку, поскольку HoverMenu DOM div даже не отображается внутри DOM span . (Интересно, происходит ли это из- HoverMenu что span .)

Какое поведение ожидается?

Ошибка не возникает. Или, по крайней мере, сообщение об ошибке яснее.

Какие версии React и какой браузер / ОС подвержены этой проблеме?

Хром 65
Реагировать 16.2
(SSR через Next 5.1)

medium Bug good first issue

Самый полезный комментарий

Хотя гидратирующие порталы не поддерживаются (https://github.com/facebook/react/issues/13097), само сообщение не имеет смысла. Нам нужно будет исследовать и исправить это.

Все 24 Комментарий

У меня аналогичная проблема, которую также можно решить повторным рендерингом на клиенте через setState.
В моем случае я пытаюсь визуализировать модальное окно внутри портала. Компонент Modal возвращает null при визуализации на сервере и создает портал на клиенте. Однако после гидратации DOM портится.

Например, если я использую его так внутри своего основного компонента:

<Modal>
This is a test
</Modal>

<div className="some-div-after-the-modal">
</div>

Вместо того, чтобы получать это после гидратации:

<!-- Inside the portal container -->
<div class="modal-wrapper">
    <div class="modal-content">This is a test</div>
</div>

<!-- In the main component -->
<div class="some-div-after-the-modal">
</div>

Я получаю это:

<!-- Inside the portal container -->
<div class="some-div-after-the-modal">
    <div class="modal-content">This is a test</div>
</div>

<!-- In the main component -->
<div class="some-div-after-the-modal">
</div>

И предупреждение такое же ( Expected server HTML to contain a matching <div> in <div> ). Я использую React 16.3 с настраиваемым методом SSR.

Я не уверен, что это предполагаемое поведение.

Хотя гидратирующие порталы не поддерживаются (https://github.com/facebook/react/issues/13097), само сообщение не имеет смысла. Нам нужно будет исследовать и исправить это.

@gaearon Цель исправления:

  • [] Определяет, что портал используется в hydrate (), а затем инвариантно выдает более правильное сообщение об ошибке.
    например, invariant violation: Portal is not support on SSR. For more detail, please refer https://github.com/facebook/react/issues/13097
  • [] Добавить тест

    • [] Если портал используется с hydrate (), должно появиться указанное выше сообщение об ошибке.

правильно?
Я готов, если это не срочно.

Я планирую черновик SSR Doc для репозитория веб-сайта, поэтому я должен быть знаком с механизмом гидратации.
Думаю, это расследование поможет моему плану.
https://github.com/facebook/react/pull/13379

Почему порталы не поддерживаются в SSR даже для отображения «ничего»?

Не похоже, что рендеринг ничего лучше - я не вижу, что отличает содержимое портала от других, если мы не считаем его стоящим рендеринга на сервере.

Мы, вероятно, вернемся к этому вместе с обновлением серверного рендерера для неопределенности.

Порталы концептуально являются клиентскими компонентами; используются для таких вещей, как модальные окна, которые обычно не хотят отображать на сервере - они также принимают элемент dom, которого renderToString не делает, потому что нет dom. Я не вижу, что с ними можно делать на сервере что-нибудь значимое - я просто также не вижу ничего ценного в бросании.

используется для таких вещей, как модальные окна

Это один вариант использования, но есть и другие, такие как боковые панели и тому подобное, которые не обязательно предназначены только для клиента.

они также принимают элемент dom

Справа - в текущем дизайне. Это могло измениться. https://github.com/facebook/react/pull/8386#issuecomment -262375265

я просто тоже не вижу ничего ценного от метания.

Ценность метания заключается в явном подтверждении того, что портал не будет работать. Вы можете легко обойти это с помощью {domNode && ReactDOM.createPortal(stuff, domNode)} или аналогичного. Потому что вам уже нужно было выполнить какую-то проверку, чтобы определить, можете ли вы получить узел DOM - так что на этом этапе у вас должно быть достаточно данных, чтобы отказаться от создания портала.

Я хотел бы исправить это как свою "первую хорошую проблему"

+1

Могу я поработать над этим вопросом?

Конечно. Я думаю, ты сможешь. Итак, как далеко вы зашли? Я тоже подумываю забрать его.

  • 2

Привет, ребята, есть идеи, как найти файл, в котором проблема, я могу его получить, пожалуйста, помогите.

Привет, вот частичный запрос на перенос для этой проблемы
https://github.com/facebook/react/pull/15473

Кто-нибудь еще занимается этим? Я бы с радостью взялся за это.

Какой у этого статус? Как я мог воспроизвести это?

Это все еще проблема?

Я тоже не получил ответа по этому поводу.

Я считаю, что статус этого вопроса все еще открыт.

Могу я заняться этим вопросом?

Здравствуйте, кто-нибудь работает над этим вопросом? Если нет, я бы взял.

если над этим никто не работает, я могу

Это все еще проблема? Кажется, что были попытки исправить это, но основная проблема в том, что некоторые люди действительно хотят, чтобы порталы работали над рендерингом на стороне сервера? Если это так, можно ли закрыть этот вопрос?

Добавление элемента div должно работать нормально

`class Para extends React.Component {
render () {
возвращение (

Некоторый текст
)

}
} `

Была ли эта страница полезной?
0 / 5 - 0 рейтинги