繁体   English   中英

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM