![](/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.