React: 使用门户网站和SSR进行保湿时出现意外警告

创建于 2018-04-15  ·  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 setState造成了双重渲染。

我不太明白那个错误告诉我什么。 无论哪种情况,都不会在服务器端呈现<div /> 。 该错误特别令人困惑,因为HoverMenu DOM div甚至没有呈现在DOM span 。 (我想知道这是否正在发生,因为HoverMenu嵌套在React 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> )。 我使用带有自定义SSR方法的React 16.3。

我不确定这是否是预期的行为。

虽然不支持补水门户网站(https://github.com/facebook/react/issues/13097),但消息本身没有任何意义。 我们需要调查并修复它。

@gaearon修复的目的是

  • []检测Portal在hydrate()中正在使用,然后通过不变式更正确地引发错误消息。
    例如invariant violation: Portal is not support on SSR. For more detail, please refer https://github.com/facebook/react/issues/13097
  • []添加测试

    • []如果Portal与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扩展了React.Component {
render(){
返回(

一些文字
)

}
}`

此页面是否有帮助?
0 / 5 - 0 等级