在其他组件中嵌入React-Sigma-v2组件出现‘容器无宽度’错误求助
解决react-sigma嵌入Accordion时的「容器无宽度」错误
问题背景
单个MyGraph组件渲染正常,但通过Array.map批量嵌入react-bootstrap的Accordion.Body时,抛出错误:
Sigma: Container has no width. You can set the allowInvalidContainer setting to true to stop seeing this error.
已尝试为所有容器、组件设置固定宽高,导入样式表,但问题仍存在。经测试,推测原因是:
- Accordion默认折叠,内部容器初始未进入可视DOM,尺寸为0,Sigma初始化无法检测到有效宽高
- 批量渲染时多实例的初始化时机冲突(类似leaflet.js的多实例渲染问题)
解决方案
1. 延迟渲染:仅在Accordion展开时渲染图表
利用Accordion的展开状态控制MyGraph的渲染时机,确保Sigma初始化时容器已具备有效尺寸:
// 父组件代码 import { useState } from 'react'; import Accordion from 'react-bootstrap/Accordion'; export const GraphAccordion = ({ data }) => { const [expandedKey, setExpandedKey] = useState(null); return ( <Accordion activeKey={expandedKey} onSelect={setExpandedKey}> {data.map((element, index) => ( <Accordion.Item key={element.id || index} eventKey={String(index)}> <Accordion.Header>图表 {index + 1}</Accordion.Header> <Accordion.Body style={{ width: "500px", height: "500px", backgroundColor: "green" }} > <div style={{ width: "500px", height: "500px" }}> {/* 仅当当前项展开时才渲染图表 */} {expandedKey === String(index) && <MyGraph data={element} />} </div> </Accordion.Body> </Accordion.Item> ))} </Accordion> ); };
同时修正MyGraph组件,确保样式属性正确传递:
// MyGraph组件代码 export const MyGraph = ({ data, style = {} }) => { const graph = treatData(data); return ( <SigmaContainer graph={graph} style={{ height: "500px", width: "500px", ...style }} > <ControlsContainer position="bottom-right"> {/* 控件内容 */} </ControlsContainer> </SigmaContainer> ); };
2. 允许无效容器+展开时强制刷新
如果需要预渲染图表,先通过allowInvalidContainer规避初始化错误,再在Accordion展开时触发Sigma重绘:
// MyGraph组件添加ref和allowInvalidContainer import { useRef, useEffect } from 'react'; export const MyGraph = ({ data, graphKey }) => { const graph = treatData(data); const sigmaRef = useRef(null); // 对外暴露刷新方法 useEffect(() => { window[`sigma_${graphKey}`] = () => { sigmaRef.current?.getSigmaInstance()?.refresh(); }; }, [graphKey]); return ( <SigmaContainer ref={sigmaRef} graph={graph} style={{ height: "500px", width: "500px" }} allowInvalidContainer={true} > <ControlsContainer position="bottom-right"> {/* 控件内容 */} </ControlsContainer> </SigmaContainer> ); };
// 父组件调用刷新方法 export const GraphAccordion = ({ data }) => { const [expandedKey, setExpandedKey] = useState(null); const handleExpand = (key) => { setExpandedKey(key); // 延迟执行,确保DOM已完成尺寸更新 setTimeout(() => { window[`sigma_${key}`]?.(); }, 100); }; return ( <Accordion activeKey={expandedKey} onSelect={handleExpand}> {data.map((element, index) => ( <Accordion.Item key={element.id || index} eventKey={String(index)}> <Accordion.Header>图表 {index + 1}</Accordion.Header> <Accordion.Body style={{ width: "500px", height: "500px", backgroundColor: "green" }} > <div style={{ width: "500px", height: "500px" }}> <MyGraph data={element} graphKey={String(index)} /> </div> </Accordion.Body> </Accordion.Item> ))} </Accordion> ); };
3. 强制容器初始尺寸可见
给包裹MyGraph的容器设置强制可见的CSS(用visibility而非display),确保Sigma初始化时能检测到尺寸:
// 父组件中包裹MyGraph的div样式 <div style={{ width: "500px", height: "500px", visibility: expandedKey === String(index) ? "visible" : "hidden", overflow: "hidden" }} > <MyGraph data={element} /> </div>
核心原因
Sigma图表初始化时需要读取容器的实际offsetWidth和offsetHeight,而Accordion折叠状态下,内部元素的尺寸为0,导致Sigma抛出错误。通过控制渲染时机、强制刷新或确保初始化时容器有有效尺寸,即可解决该问题。
内容的提问来源于stack exchange,提问作者Marek
相关产品推荐
相关产品推荐

