mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-03 23:03:09 +00:00
fix: prevent SourceEditor recreation on every content change (#624)
The mountEditor callback had content in its dependency array and was used as a React ref callback. Every content change (keystroke) gave mountEditor a new identity, causing React to destroy and recreate the entire CodeMirror editor — losing cursor position, undo history, and focus. Remove content from the dependency array and use a separate useEffect to push external content updates to the existing editor via dispatch(). The editor is now only recreated when filePath, language, or readOnly change. Co-authored-by: Test User <test@example.com> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Test User
Claude Opus 4.7
parent
6fe970651d
commit
236eabe248
@@ -1,4 +1,4 @@
|
||||
import { useRef, useCallback, memo } from "react";
|
||||
import { useRef, useCallback, useEffect, memo } from "react";
|
||||
import {
|
||||
EditorView,
|
||||
keymap,
|
||||
@@ -69,6 +69,9 @@ export const SourceEditor = memo(function SourceEditor({
|
||||
const onChangeRef = useRef(onChange);
|
||||
onChangeRef.current = onChange;
|
||||
|
||||
const contentRef = useRef(content);
|
||||
contentRef.current = content;
|
||||
|
||||
const mountEditor = useCallback(
|
||||
(node: HTMLDivElement | null) => {
|
||||
if (editorRef.current) {
|
||||
@@ -87,7 +90,7 @@ export const SourceEditor = memo(function SourceEditor({
|
||||
});
|
||||
|
||||
const state = EditorState.create({
|
||||
doc: content,
|
||||
doc: contentRef.current,
|
||||
extensions: [
|
||||
lineNumbers(),
|
||||
highlightActiveLine(),
|
||||
@@ -112,8 +115,22 @@ export const SourceEditor = memo(function SourceEditor({
|
||||
|
||||
editorRef.current = new EditorView({ state, parent: node });
|
||||
},
|
||||
[content, filePath, language, readOnly],
|
||||
[filePath, language, readOnly],
|
||||
);
|
||||
|
||||
// Sync external content changes into the editor without recreating it.
|
||||
// Only applies when the new content differs from the current document
|
||||
// (e.g. file switch or server refresh), not on every keystroke.
|
||||
useEffect(() => {
|
||||
const view = editorRef.current;
|
||||
if (!view) return;
|
||||
const current = view.state.doc.toString();
|
||||
if (current !== content) {
|
||||
view.dispatch({
|
||||
changes: { from: 0, to: current.length, insert: content },
|
||||
});
|
||||
}
|
||||
}, [content]);
|
||||
|
||||
return <div ref={mountEditor} className="h-full w-full overflow-hidden" />;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user