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

Changing editor sessions causes session/selection listeners to stop firing

Open sayomaki opened this issue 2 years ago • 0 comments

Problem

When changing the session (Ace.EditSession) of the current editor (to allow for different editing sessions but reusing the same editor component) via the editor.setSession() method, the various session/selection related events stop firing

The events includes onCursorChange, onSelectionChange, onScroll, etc.

This could be due to the way how ReactAce implements event registration for the session-based events, as they are only registered during the componentDidMount lifecycle stage for the default session.

Sample code to reproduce your issue

The following code has been tested on [email protected], [email protected], and on both react@16 and react@18.

import { useRef, useState } from 'react';
import ace, { createEditSession } from 'ace-builds';
import "ace-builds/webpack-resolver";
import AceEditor from 'react-ace';

import "ace-builds/src-noconflict/mode-javascript";
import "ace-builds/src-noconflict/ext-language_tools";

function App() {
  const aceEditorRef = useRef(null);
  const [cursorEvents, setCursorEvents] = useState(0);

  const changeSession = () => {
    const newSession = createEditSession('// new editor session\n// cursor event stops firing', 'ace/mode/javascript');
    if (aceEditorRef.current) {
      aceEditorRef.current.editor.setSession(newSession);
    }
  }

  const cursorChangeEvent = () => setCursorEvents(cursorEvents + 1);

  return (
    <div>
      <button onClick={changeSession}>Change editor session</button>
      <div>Cursor event fired: {cursorEvents} times</div>
      <AceEditor mode="ace/mode/javascript" onCursorChange={cursorChangeEvent} ref={aceEditorRef} />
    </div>
  );
}

export default App;

A simple but tedious workaround for the problem is to re-register the aforementioned events manually, right after changing sessions via editor.setSession(). However, care and caution is also needed to ensure the event is only registered once for each session, which leads to some very hacky fixes.

Possible resolution can be to track/intercept the session changes, and rebind the event listeners.

References

sayomaki avatar Sep 03 '23 04:09 sayomaki