{graphData?.nodes?.length === 0 && graphData?.edges?.length === 0 ? (
<div className="w-full h-[150px] text-center py-16 text-gray-500 border border-gray-200 rounded text-sm">
No graph to show
</div>
) : (
<>
{/* 그래프 영역 */}
<div className="w-[70%]">
<div id="cy" ref={cyRef} className="w-full h-[450px] border border-gray-200 rounded" />
</div>
{/* Legend 영역 */}
<div className="w-[30%] h-[450px] overflow-y-auto">
<Legend
graphData={graphData}
selectedElementData={selectedElementData}
labelColorMap={labelColorMap}
/>
</div>
</>
)}
위의 코드처럼, 그래프 데이터가 없을 때는 그래프 영역 대신 No graph to show라는 문구를 보여주려고 했다. 근데, 한번 해당 문구가 보여진 이후에는 다시 그래프가 나타나지 않았다.
ref 요소는 DOM 노드가 mount 되었을 때만 연결이 된다.
const myRef = useRef(null);
return show ? <div ref={myRef}>Hello</div> : null;
이때, 위 코드에서 show === false 이면 div는 렌더링 되지 않고, 따라서 myRef.current === null인 상태를 유지한다.
다시 내 코드로 돌아와서, ref.current는 <div id="cy" />가 실제로 렌더링되어 DOM에 존재할 때만 값을 가진다. 그런데 조건부 렌더링으로 <div id="cy" ref={cyRef} />가 렌더링되지 않으면, ref.current === null인데, 그러면 Cytoscape는 container: null 상태로 초기화하려고 해서 오류가 난다.
useEffect(() => {
if (!graphData || !cyInstanceRef.current) return;
const deepCopyGraphData = structuredClone(graphData);
cyInstanceRef.current.elements().remove();
cyInstanceRef.current.add([...deepCopyGraphData.nodes, ...deepCopyGraphData.edges]);
deepCopyGraphData.edges.length > 0
? cyInstanceRef.current.layout({ name: 'cose', animate: false }).run()
: cyInstanceRef.current.layout({ name: 'grid', animate: false }).run();
}, [graphData]);
graphData가 비어있는 경우 cyInstanceRef는 DOM에서 사라지면서 null이 할당되고, 위의 코드에서 다시 graphData가 생겼을 때, null인 상태에서 로직을 진행하다보니 에러가 생긴 것이었다.
아래처럼 계속해서 렌더링이 될 수 있도록 수정했더니, 이슈가 해결되었다.
<div className="w-[70%]">
<div id="cy" ref={cyRef} className="w-full h-[450px] border border-gray-200 rounded relative">
{graphData?.nodes.length === 0 && (
<div className="absolute inset-0 flex items-center justify-center text-gray-500 text-sm z-10 bg-white/80">
No graph to show
</div>
)}
</div>
</div>
<div id="cy" ref={cyRef} style={{ display: graphDataEmpty ? 'none' : 'block' }} />
위의 방법처럼 DOM은 항상 존재하고, CSS로만 숨기는 방법도 생각해볼 수 있겠다.
결과적으로 ref 요소는 DOM 노드가 mount 되었을 때만 연결이 된다는 사실을 알게 되었다.
'Frontend' 카테고리의 다른 글
| eslint 설정해보기 (5) | 2025.07.08 |
|---|---|
| 모노레포 구축하기 (1) | 2025.07.08 |
| Ratio를 유지하는 이미지 컴포넌트 (0) | 2025.02.19 |
| 번들러가 왜 필요할까? (0) | 2025.01.22 |
| 스켈레톤 UI (0) | 2025.01.16 |