react-ace
react-ace copied to clipboard
setState in onChange will block the editor
onChange(newValue) {
this.setState({ code: newValue });
console.log('change', this.state.code);
}
I have what I think is a similar problem. I put the text content of the editor in the state and set the value to the text that is in the state.
<AceEditor
value={this.state.text}
onChange={(newValue) => this.textChanged(newValue)}/>
This doesn't work properly though. I think that the editor is being re-initialized at each step which isn't much good :(
I'm still working exactly what's going on.
I think that the root of this issue is that if you change the text the component always updates.
One solution would be to add a shouldComponentUpdate() that only updates when properties have changed OR when the text property is not equal to the text displayed in the editor.
or not, apparently I still don't really get this :grin:
I'm having a similar issue
edit:
I found a workaround for my particular issue.
I was having issues trying to capture the input using a setState.
It appears that having a defaultValue was causing some sort of conflict. (which makes sense I suppose?)
I used value instead and now onChange and the editor works as (at least how I) expected.
Not sure if this is what @mjmdavis and @dyf102 were experiencing.
I was always using 'value'. I think I was just being silly.
Anyone find a solution for this issue?
I'm having this same issue.
@mbrochstein I was able to find a workaround by using Reacts shouldComponentUpdate method.
shouldComponentUpdate(nextProps, nextState) {
if (this.state.aceEditorValue !== nextState.aceEditorValue) {
return false
} else {
return true;
}
}
Then for my onChange method for the <AceEditor />
onChange = (newValue) => {
this.setState({
aceEditorValue: newValue
});
}
This will update the state of aceEditorValue with whatever is entered into the editor without re-rendering the entire component. Works for my use case.
@brendanmcgivern Thanks! I think you flipped your comparators in the shouldComponentUpdate function, but once I switched that to ===, that works perfectly!
What about this one? It works well in my project.
THE PARENT COMPONENT
// other methods ...
eventMDChange(value) {
let _html = Marked(value)
this.setState({ markdown: value, html: _html })
}
// other methods ...
THE EDITOR
<AceEditor
onChange={ (raw)=>{this.eventMDChange(raw);} }
value={ this.state.markdown }
/>
So the issue here is we're tapping into ace editor's actual change event rather than listening and rerendering. It sounds like you want to be able to tap into the period of time when a change is happening. We could have another hook in componentWillReceiveProps that prevents an update. Personally, i think @brendanmcgivern 's solution is the cleanest though.
Same issue here :/
Well, this is a huge bug and it is still there.
I tried to use react-ace with https://github.com/jaredpalmer/formik and behaviour is the same, it just stucks.
<AceEditor
mode="yaml"
theme="solarized_light"
onChange={value => {
setFieldValue("content", value);
}}
tabSize={2}
editorProps={{ $blockScrolling: true }}
value={''}
width="100%"
/>
upd
This looks not nice, but it worked out for me. The key issue, as I understand, is that you better not set state or do anything with the value right from the ace's onChange (inline). You better do it in the different component's function.
import React, { Component } from "react";
import { Formik, Form, Field } from "formik";
class AcePlusFormik extends Component {
state = { content: "" };
/**
* Special treatment for ace content
* @param {string} value
*/
setContent(value) {
this.setState({ content: value });
this.setFieldValue("content", value);
}
render() {
<Formik
initialValues={{ title: "", content: "" }}
onSubmit={values => console.log(values)}
>
{({ touched, setFieldValue }) => {
this.setFieldValue = setFieldValue;
return (
<Form>
<Field name="content">
{({ field }) => (
<React.Fragment>
<AceEditor
mode="yaml"
theme="solarized_light"
onChange={value => {
this.setContent(value);
}}
tabSize={2}
editorProps={{ $blockScrolling: true }}
value={this.state.content}
width="100%"
/>
<input type="hidden" {...field} />
</React.Fragment>
)}
</Field>
<button
className="button is-primary is-pulled-right"
style={{ marginTop: "10px" }}
type="submit"
>
Save
</button>
</Form>
);
}}
</Formik>;
}
}
Are there any solutions or workaround for functional components?
It happens when I add props debounceChangePeriod={500}