将 React 门户渲染到另一个组件 DOM 是否安全?
Is it safe to render a react portal into another component 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.
无关
为什么这不同(这里推测)?在更新门户父组件时,在协调过程中,diff 可能会发现不一致并删除门户节点。
根据我的测试,上述情况并没有发生,但我不知道我是否可以假设 React 可以处理它。那么问题来了:
将门户渲染到另一个组件是否安全DOM?
安全吗?当然可以,但它可能不会像您期望的那样工作。
首先,您可以完全将 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 之后 它。但是渲染是 运行 before dom 被更新。因此,如果 Pagination
在与 Grid
相同的扫描中呈现,则 div 可能尚未安装。
现在臭名昭著的堆栈溢出就是不要做那个答案:
只是不要那样做。 portal 的目的是让你在 React 容器之外渲染,同时让你的组件保持在 Reacts 渲染树中。如果你无论如何都在 React 渲染树中渲染,为什么不直接在那里渲染组件呢? (如果该陈述令人困惑,我怪你)
The Portals doc mention that you can render a portal in a DOM node but nothing about components DOM
这里没有提到,因为这是一般规则的特例; DOM 如果有更多惯用的方法,则不应在 React 中直接访问。
DOM 中发生大量内存泄漏。如果托管门户 (Grid
) 的组件被重新渲染而门户组件 (Pagination
) 未被渲染,这将导致分离 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.
为什么这不同(这里推测)?在更新门户父组件时,在协调过程中,diff 可能会发现不一致并删除门户节点。
根据我的测试,上述情况并没有发生,但我不知道我是否可以假设 React 可以处理它。那么问题来了:
将门户渲染到另一个组件是否安全DOM?
安全吗?当然可以,但它可能不会像您期望的那样工作。
首先,您可以完全将 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 之后 它。但是渲染是 运行 before dom 被更新。因此,如果 Pagination
在与 Grid
相同的扫描中呈现,则 div 可能尚未安装。
现在臭名昭著的堆栈溢出就是不要做那个答案:
只是不要那样做。 portal 的目的是让你在 React 容器之外渲染,同时让你的组件保持在 Reacts 渲染树中。如果你无论如何都在 React 渲染树中渲染,为什么不直接在那里渲染组件呢? (如果该陈述令人困惑,我怪你)
The Portals doc mention that you can render a portal in a DOM node but nothing about components DOM
这里没有提到,因为这是一般规则的特例; DOM 如果有更多惯用的方法,则不应在 React 中直接访问。
DOM 中发生大量内存泄漏。如果托管门户 (Grid
) 的组件被重新渲染而门户组件 (Pagination
) 未被渲染,这将导致分离 DOM,即内存泄漏。
门户组件呈现时附加门户的元素甚至可能不存在。