fix: clean up monaco diff editor (#7819)

This commit is contained in:
Jonathan Brennan 2026-03-11 05:45:27 -05:00 committed by GitHub
parent d3d45a42db
commit 08949d5167
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,4 +1,4 @@
import { ReactElement, useEffect, useRef, useState } from 'react';
import { ReactElement, useEffect, useLayoutEffect, useRef, useState } from 'react';
import { parse, print } from 'graphql';
import { editor } from 'monaco-editor';
import { MonacoDiffEditor, MonacoEditor } from '@/components/schema-editor';
@ -35,10 +35,32 @@ export const DiffEditor = (props: {
}
}, []);
const editorRef = useRef<OriginalMonacoDiffEditor | null>(null);
const modelsRef = useRef<{
original: editor.ITextModel | null;
modified: editor.ITextModel | null;
}>({ original: null, modified: null });
// useLayoutEffect cleanup runs before @monaco-editor/react's useEffect cleanup.
// This lets us call setModel(null) to detach models from the widget, removing
// Monaco's onWillDispose listeners that throw "TextModel got disposed before
// DiffEditorWidget model got reset".
useLayoutEffect(() => {
return () => {
editorRef.current?.setModel(null);
modelsRef.current.original?.dispose();
modelsRef.current.modified?.dispose();
modelsRef.current = { original: null, modified: null };
editorRef.current = null;
};
}, []);
function handleEditorDidMount(editor: OriginalMonacoDiffEditor, monaco: Monaco) {
addKeyBindings(editor, monaco);
editorRef.current = editor;
modelsRef.current = {
original: editor.getOriginalEditor().getModel(),
modified: editor.getModifiedEditor().getModel(),
};
props.onMount?.(editor.getModifiedEditor());
editor.getModifiedEditor().onDidChangeModelContent(() => {
@ -121,6 +143,8 @@ export const DiffEditor = (props: {
loading={<Spinner />}
original={sdlBefore ?? undefined}
modified={sdlAfter ?? undefined}
keepCurrentOriginalModel
keepCurrentModifiedModel
options={{
originalEditable: false,
renderLineHighlightOnlyWhenFocus: true,