React集成Forge Viewer加载Markups时的重渲染与缓存异常问题
问题分析与解决方案
初始代码的问题
- 清理逻辑错误:useEffect的返回清理代码里,误把
removeEventListener写成了addEventListener,组件卸载时没移除事件监听,重复绑定会引发不必要的重渲染和事件触发。 - 事件循环触发:在
EVENT_EDITMODE_ENTER回调里调用leaveEditMode(),会导致事件反复触发,进而引发组件持续重渲染。
更新后代码的问题及修复
当前用TOOL_CHANGE_EVENT实现后功能基本正常,但无法加载最新markups的核心原因:
- 回调函数捕获的是
markupsData的闭包旧值,当markupsData更新时,旧的监听回调还是用之前的数据,不会自动同步最新值。 - 加载新markups前没清除原有标记层,旧内容残留导致新内容无法正常覆盖。
修复后的代码示例
React.useEffect(() => { const handleToolChange = async (x) => { if (!viewer.current) return; const extension = (await viewer.current.loadExtension("Autodesk.Viewing.MarkupsCore")) as any; // 仅在切换到标记工具且有有效markups数据时执行 if (x.active && x.toolName === "markups.core" && markupsData?.id) { await extension.leaveEditMode(); // 先清除原有标记层,避免旧内容残留 extension.clearMarkups("layer_1"); // 加载最新的markups字符串 await extension.loadMarkups(markupsData.markupsString, "layer_1"); await extension.enterEditMode("layer_1"); } }; const viewerInstance = viewer.current; viewerInstance?.addEventListener(Autodesk.Viewing.TOOL_CHANGE_EVENT, handleToolChange); // 清理函数:移除事件监听,避免内存泄漏和旧回调残留 return () => { viewerInstance?.removeEventListener(Autodesk.Viewing.TOOL_CHANGE_EVENT, handleToolChange); }; }, [viewer.current, markupsData]); // 依赖项添加markupsData,确保数据更新时重新绑定监听
额外优化建议
- 缓存MarkupsCore扩展实例:避免每次事件触发都重新加载扩展,提升性能
const [markupsExt, setMarkupsExt] = React.useState(null); React.useEffect(() => { if (!viewer.current) return; viewer.current.loadExtension("Autodesk.Viewing.MarkupsCore").then(ext => setMarkupsExt(ext)); }, [viewer.current]); // 后续直接使用markupsExt即可,无需重复加载
- 主动触发markups更新:如果需要在markupsData更新时立即刷新(无需等待工具切换),可以单独加一个useEffect处理
React.useEffect(() => { if (!markupsExt || !markupsData?.id) return; const updateMarkups = async () => { await markupsExt.leaveEditMode(); markupsExt.clearMarkups("layer_1"); await markupsExt.loadMarkups(markupsData.markupsString, "layer_1"); // 如果当前正处于标记工具模式,重新进入编辑模式 if (viewer.current?.getActiveTool() === "markups.core") { await markupsExt.enterEditMode("layer_1"); } }; updateMarkups(); }, [markupsExt, markupsData]);
这样就能确保无论是否切换工具,只要markupsData更新,就能加载最新的标记内容。
内容的提问来源于stack exchange,提问作者Abed Aarabi
相关产品推荐
相关产品推荐

