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

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

不知道大家见到过这个removeChild报错没有,去年项目设置了错误崩溃的兜底后,发现上线后页面瞬间疯狂报错页面崩溃,而且根本找不到头绪,报错原因就是这个removeChild找不到节点,真的要碎了。
本地根本没有办法复现,根据报错的UA分析,更是所有机型都存在,如果遇上用户反馈,我们只能建议他们换个浏览器试试。

1. 解决原因:空节点

根据github上的查找原因,参考:https://github.com/facebook/react/issues/17256
是因为代码中使用的空节点增删的原因,也就是<></><Fragment>这个东西导致的。在移除空节点的时候react识别认为此处的节点已经为空,导致抛出异常。(当然我们自己的电脑从没出现过。。。)
目前并不清楚其内部为什么会错误识别空节点,**但是我们唯一能做的就是:禁止项目内使用空节点。**或者可以使用,但是不允许在判断条件中,三元符号的判断里,可能不知道原因就异常了。

但是很绝望就是及时我们改掉了所有的空节点,这个问题仍然没有解决,还是会报错removeChild 、 insertBefore无法识别。

2. 解决原因:文本节点

根据一阵定位,最终我找到了错误原因(之一):文本节点。它同样会可能被异常认为由空标签包裹的子节点。
比如上一个解决的错误代码:

{
  isText ? <span>111</span>: isNumber ? 111 : <span>test</span>
}

看出错误原因了吗?因为动态渲染中,如果为true,渲染的是一个span标签,而判断为false,渲染为一个纯文本节点。
文本节点和html节点的虚拟DOM节点类型是不一样的。

React删除或者插入纯文本节点时,可能由于上一个span标签导致当前节点的Diff出现问题,导致报错"没有这个Node"

解决方案:

  1. 尽量使用相同类型的包裹元素(比如始终使用<span>或者<div>等)。
  2. 纯文本节点使用DOM元素

这是一个内部机制的问题,也是我们应该避免的。

文本节点和DOM节点

比如现在我要创建一个<div>Hello, world!</div>的JSX,我要做的操作如下:

var newDiv = document.createElement('div');

// 创建一个新的文本节点
var newText = document.createTextNode('Hello, world!');

newDiv.appendChild(newText);
document.body.appendChild(newDiv);
  1. 渲染纯文本节点:
    当React遇到文本内容时,例如JSX里包含字符串:<div>Hello, world!</div>,React会对里面的字符串创建一个文本类型的Fiber节点。这个文本节点不需要创建DOM元素标签,而是直接在父DOM节点内创建文本内容。

  2. 渲染div节点:
    当遇到<div>这样的HTML元素时,React会创建对应的Fiber节点,并最终通过document.createElement创建一个DOM元素,并将其插入到DOM树中。

如果一个div节点变化成了纯文本节点,React的Diff在发现节点类型有变化时,会进行如下处理:

  • 删除旧的div节点(包括其所有的子节点)。
  • 创建并插入新的纯文本节点。
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值