fix: prevent SourceEditor recreation on every keystroke#624
Open
hobostay wants to merge 1 commit intoheygen-com:mainfrom
Open
fix: prevent SourceEditor recreation on every keystroke#624hobostay wants to merge 1 commit intoheygen-com:mainfrom
hobostay wants to merge 1 commit intoheygen-com:mainfrom
Conversation
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: Claude Opus 4.7 <noreply@anthropic.com>
jrusso1020
approved these changes
May 5, 2026
Collaborator
jrusso1020
left a comment
There was a problem hiding this comment.
Verified — mountEditor is used as a ref callback (<div ref={mountEditor}>) with content in its dep array, so every keystroke gives it a new identity. React then invokes the old callback with null (destroying the editor) and the new one with the node (rebuilding it), losing cursor/undo/focus. The fix is the canonical pattern: drop content from the callback deps, seed via a ref, and sync external changes through a separate useEffect that dispatches a single replace transaction. The current !== content guard inside the effect correctly avoids a feedback loop with the updateListener (which would otherwise re-fire onChange after every external sync). LGTM.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
mountEditorcallback hadcontentin its dependency array and was used as a React ref callback — every keystroke changedcontent, givingmountEditora new identity and triggering full editor recreationDetails
Affected file:
packages/studio/src/components/editor/SourceEditor.tsxThe fix:
contentfrom themountEditordependency array — the editor is now only recreated whenfilePath,language, orreadOnlychangecontentRefto pass initial content to the editor without subscribing to changesuseEffectthat syncs external content changes (file switches, server refreshes) into the existing editor viaview.dispatch(), without recreating itTest plan
🤖 Generated with Claude Code