Failed to execute 'removeChild' on 'Node'

5,535 阅读1分钟

项目中的操作手册部分需要进行代码高亮展示,引入了第三方插件prism.js

为了便于整个项目中使用,将其封装成一个组件。

import React from "react";
import Prism from "prismjs";
interface PropsType {  
    language: any;  code: any;
}
export default class PrismCode extends React.PureComponent<PropsType, {}> {  
    ref: any;  
    constructor(props: any) {    
        super(props);    
        this.ref = React.createRef();  
    }  
    componentDidMount() {    
        this.highlight();  
    }  
    highlight = () => {    
        if (this.ref && this.ref.current) {      
            Prism.highlightElement(this.ref.current); // 会导致Error    
        }  
    }  
    render() {    
        const { language, code} = this.props;    
        return (// pre是prism的用法        
            <pre className="line-numbers">          
                <code ref={this.ref} className={`language-${language}`}>            
                    {code.trim()}        
                </code>        
            </pre>            
        );  
    }
}

在切换两个相邻的menu时,如果都需要调用该组件,会报错NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.

经过分析发现是使用组件的问题,考虑DOM-DIff算法是比对不同的React节点,而该组件的渲染直接是第三方插件的代码,在componentDidMount阶段才进行DOM节点的挂载,在此之前是没有node节点的,故需要增加一个可识别的node节点。

    return (      
        <div>        
            <pre className="line-numbers">          
                <code ref={this.ref} className={`language-${language}`}>            
                    {code.trim()}          
                </code>        
            </pre>              
        </div>    
    );

问题解决了~~~