neg*_*aro 24 javascript reactjs
如果 state 是 true 播放 youtube 视频,并且它是 false 我想删除 youtube 播放。我的代码如下。
{this.state.isPreViewVideo && <PlayYouTube video_id="ScSn235gQx0" />}
Run Code Online (Sandbox Code Playgroud)
沙箱网址:
https://codesandbox.io/s/xryoz10k6o
繁殖方式:
如果输入表单中包含 4 位字符,则 setState 为“isPreViewVideo: true”,如果小于 false
当 state 为 true 时它工作正常,但是当 state 为 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.
Run Code Online (Sandbox Code Playgroud)
有没有办法避免或解决这个错误?
hen*_*123 30
在 playYouTube.tsx 第 78 行替换<React.Fragment>...</React.Fragment>
为<div>...</div>
Fragments 使您可以对子项列表进行分组,而无需向 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
ama*_*aux 21
Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node
如果使用 Google 翻译(或任何其他更改页面 DOM 的插件),也会引发此错误。
这在 Github 问题中有详细说明:https : //github.com/facebook/react/issues/11538
当您使用外部 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>
Run Code Online (Sandbox Code Playgroud)
当我使用打开模态时,setModalData()
我会填充modalData
一些新数据。里面的 HTML 代码modalData.sliderHtml
是这样的结构:
<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>
Run Code Online (Sandbox Code Playgroud)
当模式打开时,我调用一些 jQuery 代码来初始化滑块:
useEffect(() => {
$('.carousel').initCarousel({
// some options
});
}, [modalData]);
Run Code Online (Sandbox Code Playgroud)
然后用户可以关闭模式并单击下一个链接。滑块必须由新的图像集填充。但我收到错误: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>
Run Code Online (Sandbox Code Playgroud)
当 React 尝试更改其内容时,modalData.sliderHtml
它会执行一些神奇的 DOM 操作来删除旧结构。其中一个操作是removeChild
方法,但旧.item
元素无法在父元素中找到.carousel
,因为插件将它们移动到新.items
元素中。所以,我们得到了错误。
modalData
每次关闭模式时,我开始将内容更改回初始数据结构。
useEffect(() => {
$('#MyModal').on('hidden.bs.modal', function (e) {
setModalData(initialData);
})
}, []);
Run Code Online (Sandbox Code Playgroud)
因此,内部的所有 html 结构modalData.sliderHtml
都会再次被初始的空数据填充,并且我们在单击新链接时不会收到错误。
问题说明:
什么时候isPreViewVideo
是真的,你有这个:
<PlayYouTube video_id="ScSn235gQx0" />
Run Code Online (Sandbox Code Playgroud)
这可能呈现为这样的:
<div> <!-- the root element as rendered by PlayYouTube if isPreViewVideo is truthy -->
<embed /> <!-- the video player or whatever PlayYouTube renders -->
</div>
Run Code Online (Sandbox Code Playgroud)
现在,如果某些代码通过直接操作 DOM 并移除 root 来移除播放器div
,那么您最终会......好吧,什么都没有。
但是在 React 的虚拟 DOM 中,rootdiv
还是存在的!因此,当isPreViewVideo
出现错误时,React 会尝试将其从真实 DOM 中删除,但由于它已经消失,因此会引发错误。
解决方案:
要扩展@henrik123 的答案 -PlayYouTube
用div
这样的包装...
<div> <!-- the root element rendered if isPreViewVideo is truthy -->
<PlayYouTube video_id="ScSn235gQx0" />
</div>
Run Code Online (Sandbox Code Playgroud)
...导致呈现:
<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>
Run Code Online (Sandbox Code Playgroud)
现在,通过删除其根来删除播放器的相同代码div
使其看起来像这样:
<div> <!-- the root element rendered if isPreViewVideo is truthy -->
</div>
Run Code Online (Sandbox Code Playgroud)
现在,当isPreViewVideo
出现错误时,根存在于 React 的虚拟 DOM 和真实 DOM 中,因此删除它没有问题。它的孩子已经改变了,但在这种情况下 React 并不关心——它只需要删除根。
笔记:
其他 HTML 元素,但div
也可能工作。
笔记2:
用React.Fragment
而不是 a包装是div
行不通的,因为React.Fragment
它不会向真正的 DOM 添加任何东西。所以有了这个...
<React.Fragment>
<PlayYouTube video_id="ScSn235gQx0" />
</React.Fragment>
Run Code Online (Sandbox Code Playgroud)
......你最终还是这样:
<div> <!-- the root element as rendered by PlayYouTube if isPreViewVideo is truthy -->
<embed /> <!-- the video player or whatever PlayYouTube renders -->
</div>
Run Code Online (Sandbox Code Playgroud)
你有同样的问题。
TL;DR 解决方案:
裹PlayYouTube
带div
。
手动关闭按钮后已解决引导程序警报
如果手动关闭引导程序警报错误消息,然后再次提交表单,我会遇到确切的错误。我所做的是用额外的标签包装 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;
Run Code Online (Sandbox Code Playgroud)
造成此问题的最可能原因是 React 渲染后,React 以外的其他东西修改了 DOM。
根据受影响用户的情况,可能有几种不同的原因。
如果您的所有用户都受到影响,那么您(开发人员)可能是罪魁祸首。
原因可能是您正在使用 jQuery 或在 React 之外进行 DOM 操作。
如果普通用户受到影响,最可能的原因是 Google Chrome 翻译功能(或Edge Chromium 上的Microsoft 翻译)。
值得庆幸的是,有一个简单的解决方案:<meta>
在 HTML 中添加一个标签<head>
(Google 文档)。
<meta name="google" content="notranslate" />
Run Code Online (Sandbox Code Playgroud)
这也应该禁用 Edge Chromium 上的 Microsoft Translator。
如果只有高级用户受到影响,并且他们没有在浏览器上使用翻译功能,那么可能是浏览器扩展或某些用户脚本(很可能由 SpiderMonkey 运行)导致了问题。
归档时间: |
|
查看次数: |
30401 次 |
最近记录: |