fix(canvas): defer store disposal until next store is ready — prevent tldraw reactive signals reading disposed store during async React unmount
Some checks failed
app-ci-deploy / test-build-deploy (push) Has been cancelled

This commit is contained in:
CC Worker 2026-06-01 06:18:24 +00:00
parent 9a7cc86a75
commit 53adc74a1c

View File

@ -65,6 +65,7 @@ export default function SinglePlayerPage() {
error: ''
});
const storeRef = useRef<TLStore | null>(null);
const prevStoreRef = useRef<TLStore | null>(null); // holds old store until tldraw has unmounted cleanly
const [storeReady, setStoreReady] = useState(false);
// TLDraw user preferences
@ -139,6 +140,10 @@ export default function SinglePlayerPage() {
}, 2000);
});
// Dispose the previous store only AFTER we have a new one ready.
// Disposing while storeReady=true would crash tldraw's reactive signals.
prevStoreRef.current?.dispose();
prevStoreRef.current = null;
storeRef.current = newStore;
setStoreReady(true);
setCanvasPhase('ready');
@ -154,8 +159,13 @@ export default function SinglePlayerPage() {
snapshotServiceRef.current?.forceSaveCurrentNode().catch(() => {});
snapshotServiceRef.current?.clearCurrentNode();
snapshotServiceRef.current = null;
storeRef.current?.dispose();
storeRef.current = null;
// Don't dispose the store here — Tldraw is still subscribed via storeReady=true.
// Move the current store to prevStoreRef; it will be disposed when the next store is ready.
// This prevents tldraw's reactive signals from reading a disposed store during React's async unmount.
if (storeRef.current) {
prevStoreRef.current = storeRef.current;
storeRef.current = null;
}
setStoreReady(false);
setCanvasPhase('idle');
};