react-codemirror beforeChange event

4.4k views Asked by At

I am using react-codemirror node module as follows:

<CodeMirror 
  className={className} 
  value={this.state.code} 
  onBeforeChange={this.onBeforeChange} 
  onChange={this.onChange} 
  options={options}
/>

The change event works fine, but I can't seem to hook up with the beforeChange event. Anyone know what I am doing wrong?

I have declared handlers in my class as follows:

onBeforeChange(change) {
  console.log('calling beforeChange');
}

onChange(newCode) {
  this.setState({
    code: newCode
  });
}
2

There are 2 answers

0
scniro On BEST ANSWER

Author of react-codemirror2 here. I stumbled upon your question and wanted to follow up with a detailed answer as there are some breaking changes in 3.x. The component now ships with an UnControlled and Controlled variant based on different use cases. I see you are calling setState within the onBeforeChange callback. In your case, I'd suggest leveraging the controlled component as such...

import {Controlled as CodeMirror} from 'react-codemirror2'

<CodeMirror
  value={this.state.value}
  options={options}
  onBeforeChange={(editor, data, value) => {
    this.setState({value}); // must be managed here
  }}
  onChange={(editor, metadata, value) => {
    // final value, no need to setState here
  }}
/>

With the controlled variant, managing state is required on the value prop to see any changes.

Additionally, the UnControlled component also has an onBeforeChange callback as well, yet with different behavior as such...

import {UnControlled as CodeMirror} from 'react-codemirror2'

<CodeMirror
  value={value}
  options={options}
  onBeforeChange={(editor, data, value, next) => {
    // hook to do whatever
    next();
  }}
  onChange={(editor, metadata, value) => {
  }}
/>

Here however, onChange will be deferred until next is invoked if onBeforeChange is specified. If not, onChange will fire regardless. Important to note, though, with the UnControlled variant, the editor will always react to input changes - the difference will simply be if onChange is called or not.

These changes were inspired due to the needs of the community and I encourage you to open an issue should anything not be working as you expect.

0
danday74 On

It turns out react-codemirror does NOT expose the beforeChange event.

However, react-codemirror2 does. A switch of library fixed this for me!

My final callback code:

onBeforeChange(cm, change, callOnChange) {

  const options = Object.assign({}, DEFAULT_OPTIONS, this.props.options)

  if (options.singleLine) {
    var after = change.text.join('').replace(/\n/g, '')
    change.update(change.from, change.to, [after])
  }

  callOnChange()
}

onChange(cm, change, code) {

  this.setState({ code })

  if (this.props.onChange) {
    this.props.onChange(code)
  }
}