点击时替换Mermaid脚本并重新渲染图表的问题求助
解决React中Mermaid图表替换后未重新渲染的问题
问题描述
使用Mermaid ^10.7.0在React项目中实现点击替换Mermaid脚本并显示新图表,但替换后新脚本仅以文本形式显示,未渲染为图表。
问题分析
原代码存在以下核心问题:
render方法直接将mermaidScript作为文本输出,状态更新后先显示文本再尝试替换为SVG,存在显示冲突componentDidUpdate未添加条件判断,每次组件更新都会触发Mermaid渲染,易引发无限循环- 使用
document.getElementById直接操作DOM,不符合React状态管理的设计理念
解决方案
修改后的代码如下,核心优化点已标注:
import React from "react"; import mermaid from "mermaid"; import "./App.css"; mermaid.initialize({ startOnLoad: true, theme: "default", securityLevel: "loose", themeCSS: ` g.classGroup rect { fill: #282a36; stroke: #6272a4; } g.classGroup text { fill: #f8f8f2; } g.classGroup line { stroke: #f8f8f2; stroke-width: 0.5; } .classLabel .box { stroke: #21222c; stroke-width: 3; fill: #21222c; opacity: 1; } .classLabel .label { fill: #f1fa8c; } .relation { stroke: #ff79c6; stroke-width: 1; } #compositionStart, #compositionEnd { fill: #bd93f9; stroke: #bd93f9; stroke-width: 1; } #aggregationEnd, #aggregationStart { fill: #21222c; stroke: #50fa7b; stroke-width: 1; } #dependencyStart, #dependencyEnd { fill: #00bcd4; stroke: #00bcd4; stroke-width: 1; } #extensionStart, #extensionEnd { fill: #f8f8f2; stroke: #f8f8f2; stroke-width: 1; }`, fontFamily: "Fira Code" }); export default class App extends React.Component { state = { mermaidScript: ` sequenceDiagram Alice ->> Bob: Hello Bob, how are you? Bob-->>John: How about you John? ` }; // 使用React ref获取容器,替代直接DOM查询 mermaidContainerRef = React.createRef(); // 组件挂载时初始化渲染图表 componentDidMount() { this.renderMermaid(); } // 仅当脚本内容变化时才重新渲染,避免无限循环 componentDidUpdate(prevProps, prevState) { if (prevState.mermaidScript !== this.state.mermaidScript) { this.renderMermaid(); } } // 封装渲染逻辑,复用性更强 renderMermaid = () => { if (!this.mermaidContainerRef.current) return; // 清空容器,避免新旧内容混合 this.mermaidContainerRef.current.innerHTML = ""; mermaid.render( "mermaid-diagram", // 唯一图表ID,避免冲突 this.state.mermaidScript, (svgCode) => { this.mermaidContainerRef.current.innerHTML = svgCode; } ); }; handleClick = () => { this.setState({ mermaidScript: ` sequenceDiagram Alice ->> Bob: Hello Bob, how are you? Bob-->>John: How about you John? Bob--x Alice: I am good thanks! Bob-x John: I am good thanks! Note right of John: Bob thinks a long<br/>long time, so long<br/>that the text does<br/>not fit on a row. Bob-->Alice: Checking with John... Alice->John: Yes... John, how are you? ` }); }; // 仅渲染空容器,不再直接输出脚本文本 render() { return ( <div ref={this.mermaidContainerRef} onClick={this.handleClick}></div> ); } }
额外说明
mermaid.render的第一个参数为图表唯一ID,需确保不与页面其他元素ID重复- 渲染前清空容器可避免旧图表残留,保证显示效果纯净
- 使用React
ref操作DOM更贴合组件生命周期规范,减少潜在bug
内容的提问来源于stack exchange,提问作者Karan S
相关产品推荐
相关产品推荐

