Skip to content

Bug report: IME/dead-key composition broken in Controlled wrapper (react-codemirror2 v9.0.1 + CodeMirror 5.65.20 + React 18) #327

@mblagojevic10

Description

@mblagojevic10

We’ve run into an issue with IME/dead-key composition (international keyboard accents) when using react-codemirror2 (Controlled) on React 18.

Environment

  • react-codemirror2: 9.0.1
  • codemirror: 5.65.20
  • React: 18.x
  • Browser/OS: reproducible in modern browsers (we initially noticed it with an international keyboard layout)

What’s broken

IME/dead-key composition does not commit correctly in the Controlled wrapper.
Example: typing ' followed by e should produce é, but instead composition appears to remain active and the final composed character is not committed as expected.

Steps to reproduce

  1. Render a <Controlled /> editor with value bound to component state.
  2. Focus the editor.
  3. Switch to an international keyboard layout that supports dead-keys (e.g., US-International).
  4. Type: ' then e.
  5. Observe that the composition does not commit to é correctly (and/or subsequent edits behave incorrectly).

Suspected root cause

In the Controlled implementation, the wrapper currently cancels every beforeChange (data.cancel()) and then uses a “mirror” editor to compute the next value. This seems to break IME/dead-key composition (origin *compose), because:

  • cancelling the beforeChange prevents CodeMirror from completing the composition lifecycle
  • syncing value via setValue() during composition can also reset the input state

It looks like composition should be treated as a special case:

  • do not cancel changes when data.origin === "*compose" (or when the editor is currently composing)
  • avoid applying external value updates (setValue) while composing; instead defer until compositionend

Expected behavior

Dead-key/IME composition should work normally in Controlled mode (i.e., ' + e produces é and composition ends properly), regardless of React version or role/account type in the host app.

If you’d like, I can provide a minimal reproduction repo or a patch showing a composition-safe approach (skip cancel for *compose and defer external sync until compositionend).

Thanks!
Miloš

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions