考虑以下示例:
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是否安全?
答案 0 :(得分:5)
安全吗?当然可以,但可能无法按您期望的方式工作。
首先,您可以将dom完全转储到React创建的div
中。
我已经见过几个会质疑这个事实的React程序员,但是Reacts设计期望并在必要时直接编辑dom。如果没有,就不会有componentDidUpdate
或React refs
。
This documentation on integration with other libraries可能是最相关的。
这是瓢:
因此只需创建一个空的div并将其保留在render
中,React就不会弄乱它。
这是重点; React不能保证渲染的时间。
这意味着您不知道该元素在Pagination
呈现时是否真正存在,从而导致查询失败并且门户网站不显示。 componentDidUpdate
之所以起作用,是因为React在dom更新之后 专门运行它。但是渲染是在dom更新之前 运行的。因此,如果Pagination
与Grid
在同一扫描中渲染,则div可能尚未挂载。
现在臭名昭著的堆栈溢出只是不做那个答案:
别那样做。门户的目的是让您在React容器外进行渲染,同时将组件保持在Reacts渲染树中。如果您仍然在React渲染树中进行渲染,为什么不只是在那里渲染组件呢? (如果那句话令人困惑,我要怪你)
答案 1 :(得分:2)
Portal文档提到您可以在DOM节点中呈现门户,但是与组件DOM无关。
之所以没有提及,是因为这是一般规则的特例;如果还有更多惯用的方法,则不应在React中直接访问DOM。
DOM中发生大量内存泄漏。如果托管门户(Grid
)的组件被重新渲染而门户组件(Pagination
)未被渲染,则将导致DOM分离,即内存泄漏。
在呈现门户组件时,甚至可能不存在附加门户的元素。