React
MonacoEditor编辑多实例问题
在开发工具匠《代码对比》工具的时候,需要在一个页面渲染左右两个编辑器,原代码如下
plaintext
const handleCodeChange = useCallback((newValue: string, side: 'left' | 'right') => {
console.log(`Code change from ${side}:`, newValue);
if (side === 'left') {
setLeftCode(newValue || '');
} else {
setRightCode(newValue || '');
}
}, []);
<div className="flex gap-4">
<div className="w-1/2">
<MonacoEditor
width="100%"
height="400"
language={language}
value={leftCode}
options={options}
onChange={(newValue) => handleCodeChange(newValue, 'left')}
/>
</div>
<div className="w-1/2">
<MonacoEditor
width="100%"
height="400"
language={language}
value={rightCode}
options={options}
onChange={(newValue) => handleCodeChange(newValue, 'right')}
/>
</div>
</div>
这个时候会出现一个现象,就是即使我们在左编辑器内输入内容,实际上回调的还是右编辑器的方法,也就是hanldCodeChange里一直打印的是right
通过尝试给编辑器加key
或者ref
都没有解决,最终通过查阅,发现根本原因是因为多实例的情况下monaco
实际上是复用的model
,所以解决办法就是,将是将编辑器绑定到不同的model
下,具体代码如下
plaintext
const handleEditorDidMount = useCallback((editor, monaco, side) => {
if (side === 'left') {
leftEditorRef.current = editor;
if (!leftModelRef.current) {
leftModelRef.current = monaco.editor.createModel(
leftCode,
language,
monaco.Uri.parse('inmemory://model/left')
);
}
editor.setModel(leftModelRef.current);
editor.onDidChangeModelContent(() => {
setLeftCode(editor.getValue())
})
} else {
rightEditorRef.current = editor;
if (!rightModelRef.current) {
rightModelRef.current = monaco.editor.createModel(
rightCode,
language,
monaco.Uri.parse('inmemory://model/right')
);
}
editor.setModel(rightModelRef.current);
editor.onDidChangeModelContent(() => {
setRightCode(editor.getValue())
})
}
}, [language, leftCode, rightCode]);
<div className="flex gap-4">
<div className="w-1/2">
<MonacoEditor
width="100%"
height="400"
language={language}
value={leftCode}
options={options}
editorDidMount={(editor, monaco) => handleEditorDidMount(editor, monaco, 'left')}
/>
</div>
<div className="w-1/2">
<MonacoEditor
width="100%"
height="400"
language={language}
value={rightCode}
options={options}
editorDidMount={(editor, monaco) => handleEditorDidMount(editor, monaco, 'right')}
/>
</div>
</div>