Skip to content

Bug - CodeEditor - Loses focus and cursor position when typing first character with isUploadEnabled #12211

@ochosi

Description

@ochosi

Describe the bug

When using CodeEditor with isUploadEnabled={true} (or with a custom emptyState prop), typing the first character in an empty editor causes:

  1. The Monaco editor to lose focus
  2. The cursor position to jump back to position 0
  3. A visible flicker as the component remounts

This makes it impossible to type continuously in an empty editor - users must click back into the editor after every first keystroke, and text appears in reverse order (typing "abc" results in "cba").

Steps to reproduce

  1. Render a CodeEditor with isUploadEnabled={true}:
    <CodeEditor
      isUploadEnabled
      isCopyEnabled
      isDownloadEnabled
      onCodeChange={(code) => console.log(code)}
      code=""
      height="300px"
    />
  2. Click "Start from scratch" to dismiss the empty state and open the editor
  3. Type a character (e.g., "a")
  4. Observe: Focus is lost, you cannot continue typing
  5. Click back into the editor, type another character
  6. Observe: The new character appears at position 0, before the previous character

You can also use Image Builder's "First Boot Script" step to see the bug live. See also https://issues.redhat.com/browse/HMS-9956

Expected behavior

The editor should maintain focus and cursor position when typing, allowing continuous text input. Typing "abc" should result in "abc", not "cba".

Root cause analysis

In CodeEditor.tsx (around line 599), the render logic uses conditional JSX based on whether the code is empty:

{(isUploadEnabled || emptyState) && !value ? (
  // Branch A: Container with Dropzone, shows empty state OR editor
  <div {...getRootProps()}>
    ...
  </div>
) : (
  // Branch B: Different container structure
  <>
    ...
  </>
)}

When value transitions from "" (empty) to "a" (non-empty):

  1. The condition !value changes from true to false
  2. React sees completely different JSX structures (Branch A vs Branch B)
  3. React unmounts the entire Branch A subtree and mounts Branch B
  4. The Monaco editor instance is destroyed and recreated
  5. All editor state is lost, including focus and cursor position

The inner condition at line 608 ((showEmptyState || emptyState) && !value) correctly handles showing/hiding the empty state vs editor within the same container, but the outer condition causes the entire container to switch.

Environment

  • @patternfly/react-code-editor version: 6.4.0 (and likely all recent versions)
  • React version: 18.x
  • Browser: All browsers affected (Chrome, Firefox, Safari)
  • OS: All platforms

Additional context

This bug affects any application using CodeEditor with file upload functionality (isUploadEnabled), which is a common use case for script editors, configuration editors, and code snippet inputs.

The fix is straightforward: remove && !value from the outer condition so the container structure remains stable regardless of whether the code is empty or not. The inner condition already handles the empty state display correctly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    Status

    Needs triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions