将反应门户呈现到另一个组件DOM中是否安全?

时间:2018-12-27 19:30:27

标签: javascript reactjs react-dom

考虑以下示例:

class GridContainer extends React.Component {
  ...
  render (){
    return <div>
      <Pagination portalId="portal-id"></>
      <Grid ...>
    </div>
  }
}

class Grid extends React.Component {
  ...
  render (){
    return <div>
      <div id="portal-id"></>
      <table ...>
    </div>
  }
}

class Pagination extends React.Component {
  ...
  render (){
    return return ReactDOM.createPortal(<div>Paginator DOM...</div>, document.getElementById(this.props.portalId));
  }
}

在其他组件DOM中呈现门户是否安全?我已经对其进行了测试,但是它不可靠。 Portals文档中提到您可以在DOM节点中呈现门户,但是与组件DOM无关。

为什么会有不同(在这里推测)?在更新门户网站父级组件时,在对帐过程中,差异可能会发现不一致之处并删除门户网站节点。

从我的测试来看,上述情况没有发生,但我不知道我是否可以假设React可以解决。问:问:

将门户呈现为另一个组件DOM是否安全?

2 个答案:

答案 0 :(得分:5)

安全吗?当然可以,但可能无法按您期望的方式工作。

首先,您可以将dom完全转储到React创建的div中。

我已经见过几个会质疑这个事实的React程序员,但是Reacts设计期望并在必要时直接编辑dom。如果没有,就不会有componentDidUpdate或React refs

This documentation on integration with other libraries可能是最相关的。

这是瓢:

  • React不会接触已渲染div的内部,假设它在渲染结束时始终为空。它只会:
    • 创建新元素,此处不相关,只要您将其保留为空即可。
    • 更新最初由react创建的现有元素。
    • 删除最初由react创建的元素。

因此只需创建一个空的div并将其保留在render中,React就不会弄乱它。

这是重点; React不能保证渲染的时间。

这意味着您不知道该元素在Pagination呈现时是否真正存在,从而导致查询失败并且门户网站不显示。 componentDidUpdate之所以起作用,是因为React在dom更新之后 专门运行它。但是渲染是在dom更新之前 运行的。因此,如果PaginationGrid在同一扫描中渲染,则div可能尚未挂载。

现在臭名昭著的堆栈溢出只是不做那个答案:

别那样做。门户的目的是让您在React容器外进行渲染,同时将组件保持在Reacts渲染树中。如果您仍然在React渲染树中进行渲染,为什么不只是在那里渲染组件呢? (如果那句话令人困惑,我要怪你)

答案 1 :(得分:2)

  

Portal文档提到您可以在DOM节点中呈现门户,但是与组件DOM无关。

之所以没有提及,是因为这是一般规则的特例;如果还有更多惯用的方法,则不应在React中直接访问DOM。

DOM中发生大量内存泄漏。如果托管门户(Grid)的组件被重新渲染而门户组件(Pagination)未被渲染,则将导致DOM分离,即内存泄漏。

在呈现门户组件时,甚至可能不存在附加门户的元素。