uiwjs / react-codemirror

CodeMirror 6 component for React. @codemirror https://uiwjs.github.io/react-codemirror/
https://uiwjs.github.io/react-codemirror/
MIT License
1.61k stars 128 forks source link

How to get instance #314

Open thebpmgroup opened 2 years ago

thebpmgroup commented 2 years ago

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?

Gk0Wk commented 2 years ago

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 })]}
      />
    </>
  );
}
thebpmgroup commented 2 years ago

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

ameya730 commented 2 years ago

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

McKinleyKeys commented 2 years ago

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

thewh1teagle commented 1 year ago

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

jaywcjlove commented 1 year ago

@thewh1teagle

thewh1teagle commented 1 year ago

@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 ```js 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 (
); } ```
jaywcjlove commented 1 year ago

image

@thebpmgroup

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

@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

jaywcjlove commented 1 year ago

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

thewh1teagle commented 1 year ago

@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

jaywcjlove commented 1 year ago

@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])
thewh1teagle commented 1 year ago

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!');" />;
}
jaywcjlove commented 1 year ago

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 👍

tobiasBora commented 1 year ago

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 commented 1 year ago

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));
        }
    });
Tchaikovsky1114 commented 8 months ago

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..!