Javascript 如果没有非React DOM父级,则无法卸载React门户-如何在删除父级之前手动卸载门户?

Javascript 如果没有非React DOM父级,则无法卸载React门户-如何在删除父级之前手动卸载门户?,javascript,reactjs,react-portal,Javascript,Reactjs,React Portal,我在主react应用程序之外有一个Blaze模板应用程序,其中包含一个容器,用于在其中呈现react门户。在呈现Blaze模板时,我们加载数据并将自定义事件发送到React应用程序内的事件侦听器,然后该应用程序呈现门户 这在Chrome内部非常有效,但在InternetExplorer11中,门户和模板的渲染和去渲染都要慢得多,我们遇到了竞争条件 在Blaze模板的第二次呈现中,React经历了它的生命周期,并尝试卸载前一个门户容器的所有子级,但是-它们不存在,因为我们已经完全删除了该DOM节点

我在主react应用程序之外有一个Blaze模板应用程序,其中包含一个容器,用于在其中呈现react门户。在呈现Blaze模板时,我们加载数据并将自定义事件发送到React应用程序内的事件侦听器,然后该应用程序呈现门户

这在Chrome内部非常有效,但在InternetExplorer11中,门户和模板的渲染和去渲染都要慢得多,我们遇到了竞争条件

在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(“”)调用之后才查找容器,但这不是问题所在,因为它将remove portal事件放置在create portal事件之后(在这两个调用之间不删除html)

关于如何在Blaze替换门户的父容器之前优雅地卸载和卸载门户的任何信息都将非常有用

提前谢谢


我希望至少在某个时候成功地删除门户,但没有成功。我无法删除html。(“”)调用,因为当前模板引擎就是这样替换模板的。

当外部框架从DOM树中删除我的组件时,我也遇到了同样的问题。 在我的例子中,React安装点已被aspx UpdatePanel回发所取代。 为了修复它,我必须将我的组件移出面板,并通过React.Portal安装它

现在一切都运行得很好,但IE对removeChild函数的实现似乎有点不同——当子函数不存在时,会抛出一个错误。所以我不得不在全球范围内对其进行覆盖,以处理“NotFoundError”问题


函数isIE(){
ua=navigator.userAgent;
/*MSIE用于检测旧浏览器,Trident用于检测新浏览器*/
var为_ie=ua.indexOf(“MSIE”)>-1 | | ua.indexOf(“Trident/”)>-1;
回报就是回报;
}
if(isIE()){
//开发人员注意:当React DOM liv内的removeChildFromContainer和子容器不包含响应节点时,IE only-React JS抛出NotFoundError。
让oldRemoveChild=HTMLElement.prototype.removeChild;
HTMLElement.prototype.removeChild=函数(){
试一试{
apply(这是参数);
}
捕获(错误){
if(!!error&&!!error.message&&error.message===“NotFoundError”){
控制台。警告(“IE NotFoundError handled”)
}
否则{
投掷误差;
}
}
}
}
   <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>