Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

setState in onChange will block the editor #181

Open
dyf102 opened this issue Mar 22, 2017 · 14 comments
Open

setState in onChange will block the editor #181

dyf102 opened this issue Mar 22, 2017 · 14 comments

Comments

@dyf102
Copy link

dyf102 commented Mar 22, 2017

  onChange(newValue) {
    this.setState({ code: newValue });
    console.log('change', this.state.code);
  }
@mjmdavis
Copy link

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.

@mjmdavis
Copy link

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.

@mjmdavis
Copy link

or not, apparently I still don't really get this 😁

@mcfungster
Copy link

mcfungster commented Apr 4, 2017

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.

@mjmdavis
Copy link

mjmdavis commented Apr 4, 2017

I was always using 'value'. I think I was just being silly.

@brendanmcgivern
Copy link

Anyone find a solution for this issue?

@mbrochstein
Copy link

I'm having this same issue.

@brendanmcgivern
Copy link

brendanmcgivern commented May 5, 2017

@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

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.

@mbrochstein
Copy link

@brendanmcgivern Thanks! I think you flipped your comparators in the shouldComponentUpdate function, but once I switched that to ===, that works perfectly!

@bin16
Copy link

bin16 commented May 12, 2017

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 }
    />

@securingsincity
Copy link
Owner

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.

@Sjoerd
Copy link

Sjoerd commented Nov 24, 2017

Same issue here :/

@PavelPolyakov
Copy link

PavelPolyakov commented Nov 22, 2018

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>;
  }
}

@ddt313
Copy link

ddt313 commented Dec 26, 2023

Are there any solutions or workaround for functional components?

It happens when I add props debounceChangePeriod={500}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants