如何在React弹窗首次打开时直接渲染Mermaid流程图?
解决React Modal首次打开时Mermaid图表不立即渲染的问题
你的代码中首次打开Modal时Mermaid脚本先显示为字符串,是因为mermaid.contentLoaded()的执行时机早于Modal内的.mermaid元素完成挂载,导致Mermaid无法识别并渲染目标元素。
修改方案
通过React的useRef获取目标DOM元素,在Modal确认打开且元素存在后,手动触发Mermaid的渲染逻辑,确保元素就绪后再处理。
修改后的完整代码
import React, { useState, useRef, useEffect } from "react"; import Button from "@mui/material/Button"; import Modal from "@mui/material/Modal"; import Box from "@mui/material/Box"; import Typography from "@mui/material/Typography"; import mermaid from "mermaid"; mermaid.initialize({ startOnLoad: true }); export default function Popup() { const [open, setOpen] = useState(false); // 创建ref用于获取mermaid容器元素 const mermaidContainerRef = useRef(null); const handleClickOpen = () => { setOpen(true); }; const handleClose = () => { setOpen(false); }; const mermaidScript = `sequenceDiagram Alice->>John: Hello John, how are you? John-->>Alice: Great! Alice-)John: See you later! `; useEffect(() => { // 当Modal打开且容器元素存在时,手动渲染mermaid图表 if (open && mermaidContainerRef.current) { mermaid.init(undefined, mermaidContainerRef.current); } }, [open]); return ( <div> <Button variant="contained" onClick={handleClickOpen}> Open Modal </Button> <Modal open={open} onClose={handleClose} aria-labelledby="modal-modal-title" aria-describedby="modal-modal-description" > <Box sx={{ height: "90%", width: "90%", position: "absolute", top: "50%", left: "50%", transform: "translate(-50%, -50%)", bgcolor: "background.paper", border: "2px solid #000", boxShadow: 24, p: 4 }} > <Typography id="modal-modal-title" variant="h6" component="h2"> Mermaid Diagram </Typography> <Typography id="modal-modal-description" sx={{ mt: 2 }}> {/* 将ref绑定到mermaid容器 */} <div ref={mermaidContainerRef} className="mermaid" style={{ height: "70%", width: "70%" }} > {mermaidScript} </div> </Typography> </Box> </Modal> </div> ); }
关键说明
useRef获取DOM元素:确保能直接访问到Modal内的Mermaid容器,避免依赖全局DOM扫描。- 精准触发渲染:在
useEffect中监听open状态变化,仅当Modal打开且容器元素存在时,调用mermaid.init()手动渲染目标元素,保证DOM就绪后再执行渲染逻辑。
你也可以改用MUI Modal的onOpen回调替代useEffect,效果一致:
<Modal open={open} onClose={handleClose} onOpen={() => { if (mermaidContainerRef.current) { mermaid.init(undefined, mermaidContainerRef.current); } }} aria-labelledby="modal-modal-title" aria-describedby="modal-modal-description" > {/* ... 其余代码不变 */} </Modal>
内容的提问来源于stack exchange,提问作者Karan S
相关产品推荐
相关产品推荐

