CodeMirror react component losing focus on input

Hello, we’re trying to use CM6 with a react and redux environment.
Below is CodeMirror component. We’re using an event listener that listens to changes made to the editor. This listener also fires off updateRuleBody that updates the current rule we have. But, on each change, the editor is losing focus. Do you have any suggestions for this? What would be a good approach to go about it?

const Codemirror: React.FC<{
  editorInitialValue: string | undefined;
  editorRule: Query | Suppression | undefined;
  updateRuleBody: typeof updateRuleBody;
}> = ({editorInitialValue, editorRule, updateRuleBody, }) => {


  const [editorValue, setEditorValue] = useState<string>('');
  const [editorTreeValue, setEditorTreeValue] = useState<string[]>([]);

  const editor = useRef<EditorView>();

  const onUpdate = (editorRule: any) =>
    EditorView.updateListener.of((view: ViewUpdate) => {
      const editorDocument = view.state.doc;

      const docString = editorDocument.toString();
      cmstore.dispatch(updateEditorValue(docString));

     updateRuleBody(editorRule?.viewName.toString(), docString);
    });

  useEffect(
    function initEditorView() {
      const elem = document.getElementById('codemirror-editor')!;
      if (editor.current) {
        elem.children[0].remove();
      }

      editor.current = new EditorView({
        state: EditorState.create({
          doc: editorInitialValue,
          extensions: [
            lineNumbers(),
            highlightSpecialChars(),
            history(),
            foldGutter(),
            drawSelection(),
            EditorState.allowMultipleSelections.of(true),
            indentOnInput(),
            Prec.fallback(defaultHighlightStyle),
            bracketMatching(),
            closeBrackets(),
            autocompletion(),
            rectangularSelection(),
            highlightActiveLine(),
            highlightSelectionMatches(),
            keymap.of([
              ...closeBracketsKeymap,
              ...defaultKeymap,
              ...searchKeymap,
              ...historyKeymap,
              ...foldKeymap,
              ...commentKeymap,
              ...completionKeymap,
            ]),
            sql(),
            oneDark,
            onUpdate(editorRule),
          ],
        }),
        parent: elem as Element,
      });
    },
    [editorInitialValue],
  );

I assume you’re recreating the editor on every update. You don’t want to do that for efficiency reasons, and also because removing and recreating the focused DOM will indeed remove its focus.

Yes, unnecessary re-renders, and really unwanted indeed. Can you suggest a better approach to tackle this? would be really helpful!

Your useEffect should not depend on editorInitialValue, this should solve the issue, I think. It will produce the eslint warning probably but you can silence it — as I understand that’s the intention of the prop named editorInitialValue — to provide just the initial value for the editor.

1 Like