React DOMException:无法在“节点”上执行“ removeChild”:要删除的节点不是该节点的子节点

时间:2019-02-26 07:50:25

标签: javascript reactjs

如果状态为true可以播放youtube视频,而为false则我想删除youtube播放。 我的代码如下。

{this.state.isPreViewVideo && <PlayYouTube video_id="ScSn235gQx0" />}

沙盒网址:

https://codesandbox.io/s/xryoz10k6o

复制方法:

如果输入形式中包含4位数字符,则setState表示“ isPreViewVideo:true”,并且该值小于false

当状态为true时,它可以正常工作, 但是当状态为false时,我将遇到以下错误。

DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.

Uncaught DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.

有办法避免或解决此错误吗?

8 个答案:

答案 0 :(得分:5)

如果使用Google翻译(或其他任何更改页面DOM的插件),也会引发此错误Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node

此问题在Github问题中有详细介绍:https://github.com/facebook/react/issues/11538

答案 1 :(得分:3)

我在使用音频标签时遇到了同样的问题,我将此标签保留在两个嵌套的div中,现在可以正常工作了

答案 2 :(得分:3)

<块引用>

解决了手动关闭按钮后的引导警报

如果手动关闭引导程序警报错误消息,然后再次提交表单,我会遇到确切的错误。我所做的是用额外的标签包装 AlertError 组件。

import React from "react";

const AlertError = (props) => {
    return (
        <div> // <---- Added this
            <div className="alert alert-custom alert-notice alert-light-danger fade show" role="alert">
                <div className="alert-icon"><i className="flaticon-warning"></i></div>
                <div className="alert-text">There is an error in the form..!</div>
                <div className="alert-close">
                    <button type="button" className="close" data-dismiss="alert" aria-label="Close">
                        <span aria-hidden="true"><i className="ki ki-close"></i></span>
                    </button>
                </div>
            </div>
        </div> // <---- Added this
    );
};

export default AlertError;

答案 3 :(得分:1)

在playYouTube.tsx第78行中,替换<React.Fragment>...</React.Fragment><div>...</div>

  

片段使您可以将子级列表分组,而无需添加额外的节点   到DOM。

这说明了错误 Uncaught DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.

更多有关片段的信息,https://reactjs.org/docs/fragments.html

答案 4 :(得分:1)

问题说明:

isPreViewVideo为真时,您有以下提示:

<PlayYouTube video_id="ScSn235gQx0" />

这可能导致如下所示:

<div> <!-- the root element as rendered by PlayYouTube if isPreViewVideo is truthy -->
  <embed /> <!-- the video player or whatever PlayYouTube renders -->
</div>

现在,如果某些代码通过直接操作DOM并删除根div来删除播放器,您将最终得到……好,什么都没有。

但是在React的虚拟DOM中,根div仍然存在!因此,当isPreViewVideo出现错误时,React会尝试将其从真实DOM中删除,但由于它已经消失,因此会引发错误。

解决方案:

要扩展@ henrik123的答案-将PlayYouTube用这样的div包装起来……

<div> <!-- the root element rendered if isPreViewVideo is truthy -->
  <PlayYouTube video_id="ScSn235gQx0" />
</div>

...导致此渲染:

<div> <!-- the root element rendered if isPreViewVideo is truthy -->
  <div> <!-- the element as rendered by PlayYouTube -->
    <embed /> <!-- the video player or whatever PlayYouTube renders -->
  </div>
</div>

现在,通过删除其根div来删除播放器的相同代码使它看起来像这样:

<div> <!-- the root element rendered if isPreViewVideo is truthy -->
</div>

现在isPreViewVideo出现错误时,根存在于React的虚拟DOM和真实DOM中,因此删除它没有问题。它的孩子已经变了,但是React在这种情况下不在乎-它只需要删除根即可。

注意:

div之外的其他HTML元素也可以使用。

注释2:

React.Fragment而不是div进行包装是行不通的,因为React.Fragment不会向真实DOM添加任何内容。所以有了这个……

<React.Fragment>
  <PlayYouTube video_id="ScSn235gQx0" />
</React.Fragment>

...您仍然会遇到以下问题:

<div> <!-- the root element as rendered by PlayYouTube if isPreViewVideo is truthy -->
  <embed /> <!-- the video player or whatever PlayYouTube renders -->
</div>

您遇到同样的问题。

TL; DR解决方案:

PlayYouTube包装div

答案 5 :(得分:0)

Uncaught DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.

修复:

   unmountContainer() {
      // macro task
      setTimeout(() => {
        // refs
        if (containerEle) {
          // receive removed node
          // eslint-disable-next-line no-unused-vars
          let removedChild = document
            .querySelector('.page__wrapper')
            .removeChild(containerEle);
        }
      });
    }

答案 6 :(得分:0)

当您使用外部JS或jQuery插件时,可能会发生此错误。让我说说我的情况。

问题描述

在我的React项目中,我在页面上有一些链接,每个链接都会打开一个包含一些信息的模态以及一个其中包含图像的滑块。每个链接在滑块内都有自己的一组图像。但是我有一个模态,每个链接都是一样的。 模态数据存储在状态变量中,每次单击链接(每次模态打开),我都会更改其内容:

const initialData = { title: "", intro: "" }; // here is some empty structure of object properties, we need it for the modalResponse initialization
const [modalData, setModalData] = useState(initialData);
// ...
<div id="MyModal">
    <div className="title">{modalData.title}</div>
    <div className="intro">{modalData.intro}</div>
    <div>{modalData.sliderHtml}</div>
</div>

使用setModalData()打开模式时,我用一些新数据填充了modalDatamodalData.sliderHtml中的HTML代码类似于以下结构:

<div class="carousel">
    <div class="item"><img src="first.jpg" /></div>
    <div class="item"><img src="second.jpg" /></div>
    <div class="item"><img src="third.jpg" /></div>
</div>

模式打开后,我会调用一些jQuery代码进行滑块初始化:

useEffect(() => {
    $('.carousel').initCarousel({
        // some options
    });
}, [modalData]);

然后,用户可以关闭模​​式并单击下一个链接。滑块必须由新的图像集填充。但是我得到了错误:Uncaught DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.

错误原因

该问题的原因是,jQuery插件在初始化期间更改了html的结构。它在.carousel父级内部创建了一些新的块(向左箭头/右侧,用于导航的点等)。它将所有.item子级移动到新的.items块内!插件初始化后,我得到了这样的html结构:

<div class="carousel">
    <div class="dots">...</div>
    <div class="arrows">...</div>
    <div class="items">
        <div class="item"><img src="first.jpg" /></div>
        <div class="item"><img src="second.jpg" /></div>
        <div class="item"><img src="third.jpg" /></div>
    </div>
</div>

当React尝试更改modalData.sliderHtml的内容时,它将执行一些魔术DOM操作以删除旧结构。此操作之一是removeChild方法,但是在父.item内找不到旧的.carousel元素,因为插件将它们移到了新的.items元素内。因此,我们得到了错误。

错误修复

每次关闭模式时,我就开始将modalData的内容改回initialData结构。

useEffect(() => {
    $('#MyModal').on('hidden.bs.modal', function (e) {
        setModalData(initialData);
    })
}, []);

因此,modalData.sliderHtml中的所有html结构再次被初始的空数据填充,并且在新的链接点击上我们没有收到错误。

答案 7 :(得分:0)

我们代码的一个地方是这样的:

render() {
 if (el) return <div />

 return '';
}

用null替换''后,一切正常,没有错误。