You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

点击时替换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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 21:43:21