React-ace: Ace editor only binds commands on mount

Created on 12 Aug 2019  路  5Comments  路  Source: securingsincity/react-ace

Problem

If you pass a prop function to react-ace, it will only bind the function at the AceEditor mount. If your function prop changes, it won't use your new changed function, only the one passed in upon the first mount.

Detail the problem here, including any possible solutions.

Sample code to reproduce your issue

(Ignore the error)
Edit relaxed-goldwasser-qprrd

References

Progress on: #

Documentation bug question

Most helpful comment

@FMS-Cat how did you get this working? Using the following example I tried, it doesn't seem to work as a solution?

function Example() {
    function save() { ... }

    const ref = useRef(save)

    return (
      <AceEditor commands={[
        {
          name: 'save',
          bindKey: {
            win: 'Ctrl-enter',
            mac: 'Cmd-enter',
          },
          exec: () => ref.current(),
        },
      ]}/>
    )
}

All 5 comments

I bumped into this issue and got around it by getting the value from the Editor that is passed to the command using getValue().

So in your case you would change the handleSubmit function.

const handleSubmit = (editor) => {
  const text = editor.getValue();
  window.alert("You submitted the text: " + text);
};

https://codesandbox.io/s/confident-neumann-99zmk

Thanks for workaround! That is a decent temporary solution, but it still doesn't solve the root problem. You shouldn't be forced to pass the entire editor object to the parent. The Ace Editor component shouldn't only bind your commands on mounting. If you change the commands being passed in, it should update the component with your updated commands.

Current workaround in function components is to use useRef and assign the () => referencedFunction.current() instead as exec

@FMS-Cat how did you get this working? Using the following example I tried, it doesn't seem to work as a solution?

function Example() {
    function save() { ... }

    const ref = useRef(save)

    return (
      <AceEditor commands={[
        {
          name: 'save',
          bindKey: {
            win: 'Ctrl-enter',
            mac: 'Cmd-enter',
          },
          exec: () => ref.current(),
        },
      ]}/>
    )
}

Until this is fixed, here's more code for two workarounds discussed above

editor.getValue() [cleaner workaround]

// `onSave` shouldn't have to pass the content 
// back up the chain since onChange already did that,
// hence calling this a workaround.
function Example({ content, onChange, onSave }) {
  return (
    <AceEditor
      content={content}
      onChange={c => onChange(c)}
      commands={[{
        name: 'save',
        bindKey: { win: 'Ctrl-enter', mac: 'Cmd-enter' },
        exec: editor => onSave(editor.getValue()),
      }]}
    />
  );
}

useRef

function Example({ content, onChange, onSave }) {
  const editor = useRef(null)

  return (
    <AceEditor
      ref={editor}
      content={content}
      onChange={c => onChange(c)}
      commands={[{
        name: 'save',
        bindKey: { win: 'Ctrl-enter', mac: 'Cmd-enter' },
        exec: () => onSave(editor.current.props.value),
      }]}
    />
  );
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

dmavrin picture dmavrin  路  3Comments

Jarmahent picture Jarmahent  路  3Comments

Lyeed picture Lyeed  路  3Comments

ponelat picture ponelat  路  3Comments

burks10 picture burks10  路  3Comments