![](/img/trans.png)
[英]Use React Portal to render a child into a DOM node of the parent component
[英]React portal cannot be unmounted without non-react DOM parent - how can I unmount the portal manually before removing the parent?
我在主 React 应用程序之外有一个 Blaze 模板应用程序,其中包含一个用于在其中呈现的 React 门户的容器。 在渲染 Blaze 模板时,我们加载数据并将自定义事件发送到 React 应用程序内的事件侦听器,然后由它渲染门户。
这在 Chrome 中完美运行,但使用 Internet Explorer 11,门户和模板的渲染和反渲染都慢得多,并且我们遇到了竞争条件??
在 Blaze 模板的第二次渲染中,React 经历了它的生命周期并尝试卸载前一个门户容器的所有子级,然而 - 它们不存在,因为我们已经完全删除了那个 DOM 节点(使用 .html('') ),我们在 ReactDOM 中遇到了一个错误,其中没有找到孩子。
function removeChildFromContainer(container, child) {
if (container.nodeType === COMMENT_NODE) {
container.parentNode.removeChild(child);
} else {
container.removeChild(child); // Error on this line.
}
}
我试图通过在现有代码删除 DOM 容器之前发送自定义事件来删除卸载门户。
//Derender the previous portal if it exists
if (window.isEvalTool) {
console.log('removing the portal')
// Send an event to React to unmount the previous portal node for IE
var container = document.getElementById('eval-panel-root');
var removePortal = new CustomEvent("readyForPortalRemoval", {
detail: container
});
window.dispatchEvent(removePortal);
}
$(findingContainer).html('');
// Code that should unmount the component manually
window.addEventListener('readyForPortalRemoval', function (event) {
console.log('removing previous portal container');
var removed = ReactDOM.unmountComponentAtNode(event.detail);
console.log(removed); // This usually returns false, meaning it
// couldn't find it.
})
现在的问题是 unmountComponentAtNode 似乎不适用于我的门户(这是一个经典组件) - 即使在传递直接父容器时也是如此。 我认为这可能是因为事件不能保证立即触发,所以它可能只在 .html('') 调用之后寻找容器,但这不是问题,在之后放置删除门户事件之后创建门户事件(在这两个调用之间没有删除 html)。
关于如何在门户的父容器被 Blaze 替换之前优雅地卸载和取消渲染门户的任何信息都将非常有帮助!
提前致谢。
我希望至少在某个时候成功移除门户,但没有。 我无法删除 html.('') 调用,因为这是当前模板引擎替换模板的方式。
当我的组件被外部框架从 DOM 树中删除时,我遇到了同样的问题。 在我的情况下,React 安装点已被 aspx UpdatePanel postBack 替换。 为了修复它,我不得不将我的组件移出面板并通过 React.Portal 安装它。
现在一切正常,但似乎 IE 对 removeChild 函数的实现略有不同——当孩子不存在时,会抛出错误。 所以我不得不全局覆盖它来处理“NotFoundError”问题。
<script type="text/javascript">
function isIE() {
ua = navigator.userAgent;
/* MSIE used to detect old browsers and Trident used to newer ones*/
var is_ie = ua.indexOf("MSIE ") > -1 || ua.indexOf("Trident/") > -1;
return is_ie;
}
if (isIE()) {
//Dev note: IE only - React JS throws NotFoundError when removeChildFromContainer inside of React DOM liv and child container doens't contain coresponding node.
let oldRemoveChild = HTMLElement.prototype.removeChild;
HTMLElement.prototype.removeChild = function () {
try {
oldRemoveChild.apply(this, arguments);
}
catch (error) {
if (!!error && !!error.message && error.message === "NotFoundError") {
console.warn("IE NotFoundError handled")
}
else {
throw error;
}
}
}
}
</script>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.