0

I am using two script editors (based on AceEditor) within one form, each uses separate completer. Currently completer is instantiated inside a component like this:

const langTools = ace.require("ace/ext/language_tools");
langTools.addCompleter(completer);

where completer is a prop.

This approach results in merged completions for every script field (within one form) as completers use a singleton inside language_tools.

To clarify completer1 should suggest "foo", completer2 should suggest "bar", but currently both completers suggest "foo", "bar"

In vanilla ace-editor it is recommended to copy editor completers to avoid using them by reference e.g.:

editor.completers = editor.completers.slice();
editor.completers.push(myCompleter);

Is there a way to achieve a similar result inside react-ace component?

jckmlczk
  • 359
  • 4
  • 11

1 Answers1

0

It turned out to be as simple as using a ref to <AceEditor ref={ref} {...props}/> and then instead of relying on language_tools using ref.current.editor.completers in a similar fashion to vanilla ace-editor solution.

I ended with creating a hook for handling completer initialization and clean-up.

function useCompleter(completer?: CompleterInterface) {
  // ref is required to access `editor` of vanilla ace-editor
  const ref = useRef<ReactAce>(null);

  // Init completer
  useEffect(() => {
    // Apply optional completer
    if (completer && ref?.current) {
      // prevent using editor.completers by reference, so separate completers per editor are possible
      ref.current.editor.completers = ref.current.editor.completers.slice();
      ref.current.editor.completers.push(completer);
    }
    return () => {
      if (completer && ref?.current) {
        ref.current.editor.completers = [];
      }
    };
  }, [completer]);

  return ref;
}
jckmlczk
  • 359
  • 4
  • 11