react-codemirror icon indicating copy to clipboard operation
react-codemirror copied to clipboard

How to get instance

Open thebpmgroup opened this issue 2 years ago • 17 comments

How do you get access to the codemirror editor instance so that you can use the api?

For example

https://codemirror.net/doc/manual.html#api

See

doc.markText(from: {line, ch}, to: {line, ch}, ?options: object)

So how can I get access to an editor instance so I can get the doc object?

thebpmgroup avatar May 11 '22 08:05 thebpmgroup

If you are currently using the latest version of uiwjs/react-codemirror, then you can get the EditorView, EditorState and HTMLDivElement instances of CodeMirror with the ref parameter:

import React from "react";
import CodeMirror, { ReactCodeMirrorRef } from "@uiw/react-codemirror";
import { javascript } from "@codemirror/lang-javascript";

export default function App() {
  const refs = React.useRef<ReactCodeMirrorRef>({});
  React.useEffect(() => {
    if (refs.current?.view) console.log('EditorView:', refs.current?.view);
    if (refs.current?.state) console.log('EditorState:', refs.current?.state);
    if (refs.current?.editor) console.log('HTMLDivElement:', refs.current?.editor);
  }, [refs.current]);
  return (
    <>
      <CodeMirror
        ref={refs}
        value="console.log('hello world!');"
        height="200px"
        extensions={[javascript({ jsx: true })]}
      />
    </>
  );
}

Gk0Wk avatar May 14 '22 13:05 Gk0Wk

Thank you so much, that is exactly what I needed!

thebpmgroup avatar May 16 '22 19:05 thebpmgroup

@thebpmgroup Were you able to get doc.markText ? If yes, can you please clarify how did you get it ? Thanks, Ameya

ameya730 avatar Jun 16 '22 11:06 ameya730

@ameya730 I think doc.markText was a CodeMirror 5 feature. For CodeMirror 6, you might want to look into Decoration.mark.

McKinleyKeys avatar Jul 08 '22 10:07 McKinleyKeys

It doesn't work anymore, when using the same code like @Gk0Wk provided, I get only the HTMLDivElement, but I don't get state and view, they undefined

thewh1teagle avatar May 22 '23 15:05 thewh1teagle

  • https://github.com/uiwjs/react-codemirror/issues/499#issuecomment-1556070183

@thewh1teagle

jaywcjlove avatar May 22 '23 16:05 jaywcjlove

@jaywcjlove I try to use it in useEffect but the state and view is undefined my goal is to set default line number. so the editor will be positioned to specific line at first render.

App.ts
import React, { useRef, useState } from "react";
import CodeMirror from "@uiw/react-codemirror";
import { javascript } from "@codemirror/lang-javascript";

export default function App() {
  const $edit = useRef();
  const [val, setVal] = useState("console.log('hello world!');");
  const onChange = React.useCallback((value, viewUpdate) => {
    console.log("value:", value);
  }, []);
  const onRefChange = () => {
    $edit.current.view.dispatch({
      changes: { from: 0, to: 12, insert: "test" + new Date() }
    });
  };
  /* --------- here -------- */
  useEffect(() => {
    console.log($edit.current.state) // undefined
    console.log($edit.current.view) // undefined
  }, [$edit.current])

  return (
    <div>
      <button onClick={() => setVal("Time: " + new Date())}>
        Change Value
      </button>
      <button onClick={onRefChange}>Ref Change Value</button>
      <CodeMirror
        value={val}
        ref={$edit}
        height="200px"
        theme="dark"
        extensions={[javascript({ jsx: true })]}
        onChange={onChange}
      />
    </div>
  );
}

thewh1teagle avatar May 22 '23 17:05 thewh1teagle

image

@thebpmgroup

useEffect(() => {
  console.log($edit.current.state) // undefined
  console.log($edit.current.view) // undefined
}, [
-  $edit.current
+  $edit
])

jaywcjlove avatar May 22 '23 17:05 jaywcjlove

@jaywcjlove That's working because you test it on CodeSandbox. refresh the page and see that in the first useEffect state and view are undefined

image

thewh1teagle avatar May 22 '23 18:05 thewh1teagle

@thebpmgroup https://codesandbox.io/s/react-codemirror-example-codemirror-6-https-github-com-uiwjs-react-codemirror-issues-314-w64xo4

jaywcjlove avatar May 22 '23 18:05 jaywcjlove

@jaywcjlove

Here you can see also in the link you sent. Tried in Firefox, Chrome
To reproduce it, you need to refresh the page and see the initial useEffect log into the console image

thewh1teagle avatar May 22 '23 18:05 thewh1teagle

@thebpmgroup I didn't find a better solution, but the following solution may help you:

useEffect(()=> {
  console.log('$edit:', $edit)
  setTimeout(() => {
    console.log('$edit:view:', $edit.current?.view)
    console.log('$edit:state:', $edit.current?.state)
  }, 300)
  console.log('$edit:', $edit.current?.view)
}, [$edit])

jaywcjlove avatar May 22 '23 19:05 jaywcjlove

It's a bug in the library... I found this workround:

import CodeMirror from "@uiw/react-codemirror";
import { useRef } from "react";

export default function App() {
  const ref = useRef();

  function refCallack(editor) {
    if (!ref.current && editor?.editor && editor?.state && editor?.view) {
      // first time we got ref, similar to useEffect
      console.log(editor); // do something with editor
      ref.current = editor; // store it
    }
  }
  return <CodeMirror ref={refCallack} value="console.log('hello world!');" />;
}

thewh1teagle avatar May 22 '23 19:05 thewh1teagle

https://codesandbox.io/embed/react-codemirror-example-codemirror-6-https-github-com-uiwjs-react-codemirror-issues-314-w64xo4?fontsize=14&hidenavigation=1&theme=dark

@thewh1teagle 👍

jaywcjlove avatar May 23 '23 03:05 jaywcjlove

Hum, I’m a bit lost as well: how do you get access to doc that is needed all over the API, for instance to do replaceSelection? I tried:

    const onHelperMenuClick = useCallback((e) => {
        // Works, but is not what I want:
        // refCodemirror.current.view.dispatch({
        //     changes: { from: 0, to: 1, insert: "test" + new Date() }
        // });
        // Fails:
        if (refCodemirror.current) {
            console.log('HTMLDivElement:', refCodemirror.current.editor);
            const doc = refCodemirror.current.editor.getDoc();
            console.log(doc);
            doc.replaceSelection(e.key);
        }
    });

tobiasBora avatar Jun 01 '23 19:06 tobiasBora

Oh, seems like I needed to send this to dispatch, like:

    const onHelperMenuClick = useCallback((e) => {
        // https://github.com/uiwjs/react-codemirror/issues/314
        if (refCodemirror.current) {
            console.log('HTMLDivElement:', refCodemirror.current.editor);
            const doc = refCodemirror.current.view.state;
            refCodemirror.current.view.dispatch(doc.replaceSelection(e.key));
        }
    });

tobiasBora avatar Jun 01 '23 19:06 tobiasBora

It's a bug in the library... I found this workround:

import CodeMirror from "@uiw/react-codemirror";
import { useRef } from "react";

export default function App() {
  const editorRef = useRef<ReactCodeMirrorRef>();

  function editorRefCallack(editor: ReactCodeMirrorRef) {
    if (!editorRef.current && editor?.editor && editor?.state && editor?.view) {
      
      console.log(editor); 
      editorRef.current = editor; 
    }
  }
  return <CodeMirror ref={editorRefCallback} value="console.log('hello world!');" />;
}

it works! thank you so much..!

Tchaikovsky1114 avatar Dec 20 '23 05:12 Tchaikovsky1114