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

Reference to the AceEditor in a functional component

Open arunkumar413 opened this issue 3 years ago • 4 comments

Hi Team,

How to access the reference of AceEditor component in a functional component using useRef hook? I'd like to enable find, findAll features in the editors. It seems that the ace editor comes with a default find box. Could you please share more details on how I can achieve my requirement?

Thanks, Arun

arunkumar413 avatar Aug 06 '22 05:08 arunkumar413

You can add a ref prop to the AceEditor Component using ref={aceEditor} and then you declare a useRef hook aceEditor=useRef(). Then you can access the original editor instance using aceEditor.current.editor. This example shows using getSelectionRange() to grab the current line number that is being edited.

The trick is remembering that the react useRef hook returns an object { current : <storedobj>} so in this case to access the main editor instance as you would in vanilla js you need to say <refname>.current.editor

const Editor = (props) => {
    const aceEditor = useRef();

    function onChange(newValue){
        console.log(aceEditor.current.editor.getSelectionRange().start.row + 1)
    }
    

    return (
       <AceEditor
		id="ace_editor"
                ref={aceEditor}
		className="editor_code"
		mode="python"
		theme="dracula"
		onChange={onChange}
		name="UNIQUE_ID_OF_DIV"
		editorProps={{ $blockScrolling: true }}
		commands={[]}
		setOptions={editorOptions}
	/>
    )
}


wfmonster avatar Aug 20 '22 00:08 wfmonster

@wfmonster Thanks a lot for the detailed explanation. This will be of great use. Also can we access the editor reference anywhere in the code? Or is it just that we can access only in the onChange handler.

arunkumar413 avatar Aug 20 '22 15:08 arunkumar413

You should be able to access it anywhere. For example, to use getSelectedText() I used onSelectionChange={onSelection} prop on the ace editor and created an onSelection function. I was unable to get some things to work using event handlers as I sometimes do using useEffect. It seems the event handlers for some things such as what used to be accessed via editor.session.selection.on(...) in the regular a docs can now be accessed via event handlers on the react component. You can find a list of supported events here: https://reactjs.org/docs/events.html.

[selectedText, setSelectedText] = useState("")
... 

function onSelection(selection) {
        const selected = aceEditor.current.editor.getSelectedText();
        setSelectedValue(selected);  
}

As another example I was also able to get the event : editor.session.selection.on("changeCursor", function (e) {...}) to work using the onCursorChange={handleCursorChange} prop.

function handleCursorChange (event) { 
        const line = aceEditor.current.editor.getSelectionRange().start.row + 1;
        console.log(line);
}

And for the sake of clarity and for others that are looking for updated answers on using react ace inside of functional components. This is what the above component will look like.

const Editor = (props) => {
      const aceEditor = useRef();
      [selectedText, setSelectedText] = useState("")
      
      function onChange(newValue){
          console.log(aceEditor.current.editor.getSelectionRange().start.row + 1)
      }

      function onSelection(selection) {
              const selected = aceEditor.current.editor.getSelectedText();
              setSelectedValue(selected);  
      }
      
      function handleCursorChange (event) { 
              const line = aceEditor.current.editor.getSelectionRange().start.row + 1;
              console.log(line);
      }

   return (
       <AceEditor
		id="ace_editor"
                ref={aceEditor}
		className="editor_code"
		mode="python"
		theme="dracula"
		onChange={onChange}
                onSelectionChange={onSelection}              /*selectiongchange event*/
                onCursorChange={handleCursorChange}  /*cursorchange event*/
		name="UNIQUE_ID_OF_DIV"
		editorProps={{ $blockScrolling: true }}
		commands={[]}
		setOptions={editorOptions}
	/>
    )
}

wfmonster avatar Aug 20 '22 16:08 wfmonster

how its look in typescript?

xkomiks avatar Jan 12 '23 14:01 xkomiks