Replacing full content of editor multiple times doesn't work because of doc.length in transaction (react-codemirror)

Hello,

I’m new to CodeMirror 6 and I would like to allow a user to replace the content of a CodeMirror input with a javascript string. I used this thread on this board to come up with the following minimal solution (using React):

import React from "react";
import CodeMirror from "@uiw/react-codemirror";

function TestComponent(props) {
  let cmRef = React.useRef();

  function replaceEditorContent() {
    console.log(cmRef?.current.state?.doc.length);  // Always outputs: 2
    const transaction = cmRef?.current?.view?.state.update({
      changes: {
        from: 0,
        to: cmRef?.current.state?.doc.length,
        insert: "[bcd]",
      },
      // selection: { anchor: 0 },
    });

    if (transaction) {
      cmRef?.current?.view?.dispatch(transaction);
    }
  }

  return (
    <div>
      <CodeMirror
        ref={cmRef}
        value="aa"
      />
      <button onClick={replaceEditorContent}>Replace text</button>
    </div>
  );
}

export default TestComponent;

However, this only works well the first time, when I press the button again the doc.length is still considered to be 2, giving successively the following values :

aa                 (correct)
[bcd]              (correct)
[bcd]cd]           (incorrect, should be [bcd])

The problem is that doc.length is always 2, while it shoud be 5 after replacing the text once. I wonder if this error comes from misusing CodeMirror or misusing React.

Here is an interactive version of this code: PlayCode demo

Thank you in advance for your help!

I’d assume there is some React magic (or something in react-codemirror) going on, and I can’t say much about that. A regular CodeMirror EditorView will immediately, synchronously replace its .state property after you dispatch a transaction to it.

Thank you for your advice, I took a look at the react-codemirror closed issues on GitHub and found the solution here.

Here is the solution if someone faces the same issue as me in the future:
cmRef?.current?.state is actually a misleading path because it actually refers to the original state of the CodeMirror component. The current state is accessed through cmRef?.current?.view?.state.

1 Like