fix: drop StrictMode to stop double-mounting Viewer2D

Viewer2D (ported unchanged) has no dispose/teardown API — it attaches
permanent window listeners and starts its own rAF render loop in the
constructor. React StrictMode's dev-only mount→unmount→remount cycle
was constructing it twice into the same container with no way to tear
the first instance down, leaving two overlapping canvases and broken
rendering (load reported success but nothing appeared on screen).
Also defensively clear the container's children before construction
so a future remount (e.g. Fast Refresh) can't repeat this.

Refs #1
This commit is contained in:
minsung committed 2026-10-12 17:53:33 +09:00
1 parent c7a782f19c
commit 96c6b780ce
2 files changed
+14 -8

No files matched your search

+8 -2
View File
@@ -78,8 +78,14 @@ export function useDwgViewer() {
// mount Viewer2D once
useEffect(() => {
if (!containerRef.current) return;
const viewer = new Viewer2D(containerRef.current);
const container = containerRef.current;
if (!container) return;
// Viewer2D has no dispose/teardown API (permanent window/canvas
// listeners, its own rAF loop) — defensively clear any leftover canvas
// from a prior construction (e.g. a dev Fast Refresh remount) so it
// never stacks two live WebGL contexts in the same container.
container.replaceChildren();
const viewer = new Viewer2D(container);
viewerRef.current = viewer;
viewer.setTheme(true);
viewer.onSelect((entity) => setSelectedEntity(entity));
+6 -6
View File
@@ -1,10 +1,10 @@
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';
import './index.css';
createRoot(document.getElementById('root')!).render(
<StrictMode>
<App />
</StrictMode>,
);
// No <StrictMode>: Viewer2D (ported unchanged from the vanilla app) has no
// dispose/teardown API and attaches permanent window/canvas listeners in its
// constructor. StrictMode's dev-only mount→unmount→remount double-invoke
// would construct it twice into the same container with no way to tear the
// first instance down, leaving two overlapping WebGL canvases.
createRoot(document.getElementById('root')!).render(<App />);