簡體   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